home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / custom.c < prev    next >
C/C++ Source or Header  |  1997-07-04  |  169KB  |  5,698 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * Custom chip emulation
  5.   * 
  6.   * Copyright 1995, 1996, 1997 Bernd Schmidt
  7.   * Copyright 1995 Alessandro Bissacco
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include <ctype.h>
  14. #include <assert.h>
  15.  
  16. #include "config.h"
  17. #include "options.h"
  18. #include "gensound.h"
  19. #include "sounddep/sound.h"
  20. #include "events.h"
  21. #include "uae.h"
  22. #include "my_memory.h"
  23. #include "custom.h"
  24. #include "readcpu.h"
  25. #include "newcpu.h"
  26. #include "cia.h"
  27. #include "disk.h"
  28. #include "blitter.h"
  29. #include "xwin.h"
  30. #include "joystick.h"
  31. #include "audio.h"
  32. #include "keybuf.h"
  33. #include "serial.h"
  34. #include "osemu.h"
  35. #include "autoconf.h"
  36. #include "threaddep/penguin.h"
  37.  
  38. #ifdef X86_ASSEMBLY
  39. #define LORES_HACK
  40. #endif
  41. #define SPRITE_COLLISIONS
  42.  
  43. /*
  44.  * Several people have tried this define, with not much success. Turning on
  45.  * AGA garbles the screen. A place you could start looking is the calcdiw()
  46.  * function - the AGA timing parameters are different, and apparently I
  47.  * haven't figured out the correct formula yet. Pity, the current one looks
  48.  * logical.
  49.  * 
  50.  * @@@ Probably won't compile in this version.
  51.  */
  52.  
  53. /* #define EMULATE_AGA */
  54.  
  55. #ifndef EMULATE_AGA
  56. #define AGA_CHIPSET 0
  57. #else
  58. #define AGA_CHIPSET 1
  59. #endif
  60.  
  61. #define SMART_UPDATE 1
  62.  
  63. #ifdef SUPPORT_PENGUINS
  64. #undef SMART_UPDATE
  65. #define SMART_UPDATE 1
  66. #endif
  67.  
  68. #if AGA_CHIPSET == 1
  69. #define MAX_PLANES 8
  70. #else
  71. #define MAX_PLANES 6
  72. #endif
  73.  
  74. /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
  75.  * on-screen. We don't emulate this. Instead, we cheat with the copper to
  76.  * compensate (much easier that way). */
  77. #define COPPER_MAGIC_FUDGE -9
  78. /* We ignore that many lores pixels at the start of the display. These are
  79.  * invisible anyway due to hardware DDF limits. */
  80. #define DISPLAY_LEFT_SHIFT 0x38
  81. static int lores_factor, lores_shift, sprite_width;
  82.  
  83. #define PIXEL_XPOS(HPOS) (((HPOS)*2 - DISPLAY_LEFT_SHIFT) << lores_shift)
  84.  
  85. /* @@@ Is maxhpos + 4 - 1 correct? (4 less isn't enough) */
  86. #define max_diwlastword (PIXEL_XPOS(maxhpos + 4 -1))
  87.  
  88. /* These are default values for mouse calibration.
  89.  * The first two are default values for mstepx and mstepy.
  90.  * The second line set the horizontal and vertical offset for amiga and X 
  91.  * pointer matching
  92.  */
  93.  
  94. #define defstepx (1<<16)
  95. #define defstepy (1<<16)
  96. #define defxoffs 0
  97. #define defyoffs 0
  98.     
  99. /* Values below define mouse auto calibration process.
  100.  * They are not critical, change them if you want.
  101.  * The most important is calweight, which sets mouse adjustement rate */ 
  102.  
  103. static const int docal = 60, xcaloff = 40, ycaloff = 20;
  104. static const int calweight = 3;
  105. static int lastsampledmx, lastsampledmy;
  106.  
  107.  /*
  108.   * Events
  109.   */
  110.  
  111. unsigned long int cycles, nextevent, is_lastline, did_reset;
  112. struct ev eventtab[ev_max];
  113.  
  114. frame_time_t vsynctime, vsyncmintime;
  115.  
  116. int vpos;
  117. uae_u16 lof;
  118. static int lof_changed = 0, interlace_seen = 0;
  119.  
  120. static int copper_waiting_for_blitter, copper_active;
  121. static const int dskdelay = 2; /* FIXME: ??? */
  122.  
  123. static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
  124. static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
  125.  
  126. static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
  127.  
  128. /*
  129.  * Big lookup tables
  130.  */
  131.  
  132. static uae_u32 hirestab_h[256][2];
  133. static uae_u32 lorestab_h[256][4];
  134.  
  135. static uae_u32 hirestab_l[256][1];
  136. static uae_u32 lorestab_l[256][2];
  137.  
  138. static uae_u32 sprtaba[256],sprtabb[256];
  139. static uae_u32 clxtab[256];
  140.  
  141.  
  142. /*
  143.  * Hardware registers of all sorts.
  144.  */
  145.  
  146. static int fmode;
  147.  
  148. static uae_u16 cregs[256];
  149.  
  150. uae_u16 intena,intreq;
  151. uae_u16 dmacon;
  152. uae_u16 adkcon; /* used by audio code */
  153.  
  154. static uae_u32 cop1lc,cop2lc,copcon;
  155.  
  156. /* This is but an educated guess. It seems to be correct, but this stuff
  157.  * isn't documented well. */
  158. enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop };
  159. static enum sprstate sprst[8];
  160. static int spron[8];
  161. static uaecptr sprpt[8];
  162. static int sprxpos[8], sprvstart[8], sprvstop[8];
  163.  
  164. static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat;
  165. static uae_s16  bpl1mod,bpl2mod;
  166.  
  167. static uaecptr bplpt[8];
  168. #ifndef SMART_UPDATE
  169. static char *real_bplpt[8];
  170. #endif
  171.  
  172. /*static int blitcount[256];  blitter debug */
  173.  
  174. struct color_entry {
  175. #if AGA_CHIPSET == 0
  176.     /* X86.S expects this at the start of the structure. */
  177.     xcolnr acolors[32];
  178.     uae_u16 color_regs[32];
  179. #else
  180.     uae_u32 color_regs[256];
  181. #endif
  182. };
  183.  
  184. static struct color_entry current_colors;
  185. struct color_entry colors_for_drawing;
  186. static unsigned int bplcon0,bplcon1,bplcon2,bplcon3,bplcon4;
  187. static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0;
  188. static unsigned int diwstrt,diwstop,ddfstrt,ddfstop;
  189. static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
  190. static int sprarmed[8], sprite_last_drawn_at[8];
  191. static int last_sprite_point, nr_armed;
  192. static uae_u16 clxdat, clxcon;
  193. static int clx_sprmask;
  194. static uae_u32 dskpt;
  195. static uae_u16 dsklen,dsksync;
  196.  
  197. static int mouse_x, mouse_y;
  198. int joy0button, joy1button;
  199. unsigned int joy0dir, joy1dir;
  200. static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
  201. static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
  202. static int sprvbfl;
  203.  
  204. static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate;
  205. static int ievent_alive = 0;
  206. static uae_u32 coplc;
  207. static unsigned int copi1,copi2;
  208.  
  209. static enum copper_states {
  210.     COP_stop, COP_read, COP_do_read, COP_read_ignore, COP_do_read_ignore, COP_wait, COP_morewait, COP_move, COP_skip
  211. } copstate;
  212. /* The time the copper needs for one cycle depends on bitplane DMA. Whenever
  213.  * possible, we calculate a fixed value and store it here. */
  214. static int copper_cycle_time;
  215.  
  216. static int dsklength;
  217.  
  218. static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
  219. static int diwfirstword,diwlastword;
  220. static enum { DIW_waiting_start, DIW_waiting_stop } diwstate, hdiwstate;
  221.  
  222. int dskdmaen; /* used in cia.c */
  223.  
  224. /* 880 isn't a magic number, it's a safe number with some padding at the end.
  225.  * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
  226.  * to figure out the exact space needed. */
  227. union {
  228.     /* Let's try to align this thing. */
  229.     double uupzuq;
  230.     long int cruxmedo;
  231.     unsigned char apixels[880];
  232. } pixdata;
  233.  
  234. uae_u32 ham_linebuf[880];
  235. uae_u32 aga_linebuf[880], *aga_lbufptr;
  236.  
  237. char *xlinebuffer;
  238. int next_lineno;
  239. static int nln_how;
  240.  
  241. static int *amiga2aspect_line_map, *native2amiga_line_map;
  242. static char **row_map;
  243. static int max_drawn_amiga_line;
  244.  
  245. /*
  246.  * Statistics
  247.  */
  248.  
  249. /* Used also by bebox.cpp */
  250. unsigned long int msecs = 0, frametime = 0, timeframes = 0;
  251. static unsigned long int seconds_base;
  252. int bogusframe;
  253.  
  254. /*
  255.  * helper functions
  256.  */
  257.  
  258. int inhibit_frame;
  259. static int framecnt = 0;
  260. static int frame_redraw_necessary;
  261. static unsigned long n_frame_count;        //xxx ATB
  262. static unsigned long m_timera,m_timerb; //xxx ATB
  263. unsigned long m_FPS;                     //xxx ATB
  264. extern int showFPS;                        //xxx ATB
  265. static __inline__ void count_frame(void)
  266. {
  267.     framecnt++;
  268. //xxx ATB    
  269.     n_frame_count++;
  270.     if (n_frame_count==50)
  271.     { if (showFPS) {
  272.         m_timera=TickCount();
  273.         m_FPS=3000/((double)(m_timera-m_timerb));
  274.         m_timerb=m_timera;
  275.         n_frame_count=0;
  276.         }
  277.     }
  278.     if (framecnt >= currprefs.framerate)
  279.     framecnt = 0;
  280. }
  281.  
  282. static __inline__ void setclr(uae_u16 *p, uae_u16 val)
  283. {
  284.     if (val & 0x8000) {
  285.     *p |= val & 0x7FFF;
  286.     } else {
  287.     *p &= ~val;
  288.     }
  289. }
  290.  
  291. __inline__ int current_hpos(void)
  292. {
  293.     return cycles - eventtab[ev_hsync].oldcycles;
  294. }
  295.  
  296. static __inline__ uae_u8 *pfield_xlateptr(uaecptr plpt, int bytecount)
  297. {
  298.     if (!chipmem_bank.check(plpt,bytecount)) {
  299.     static int count = 0;
  300.     if (!count)
  301.         count++, write_log ("Warning: Bad playfield pointer\n");
  302.     return NULL;
  303.     }
  304.     return chipmem_bank.xlateaddr(plpt);
  305. }
  306.  
  307. static void calculate_copper_cycle_time (void)
  308. {
  309.     if (diwstate == DIW_waiting_start || !dmaen (DMA_BITPLANE)) {
  310.     copper_cycle_time = 2;
  311.     return;
  312.     }
  313.     copper_cycle_time = corrected_nr_planes_from_bplcon0 <= 4 ? 2 : -1;
  314. }
  315.  
  316. struct vidbuf_description gfxvidinfo;
  317.  
  318. /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
  319. typedef void (*line_draw_func)(int, int);
  320.  
  321. #define LINE_UNDECIDED 1
  322. #define LINE_DECIDED 2
  323. #define LINE_DECIDED_DOUBLE 3
  324. #define LINE_AS_PREVIOUS 4
  325. #define LINE_BORDER_NEXT 5
  326. #define LINE_BORDER_PREV 6
  327. #define LINE_DONE 7
  328. #define LINE_DONE_AS_PREVIOUS 8
  329. #define LINE_REMEMBERED_AS_PREVIOUS 9
  330.  
  331. static char *line_drawn;
  332. static char linestate[(maxvpos + 1)*2 + 1];
  333.  
  334. static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
  335. static int linetoscr_x_adjust_bytes;
  336. static int thisframe_y_adjust, prev_y_adjust, thisframe_first_drawn_line, thisframe_last_drawn_line;
  337. static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
  338. static int extra_y_adjust;
  339.  
  340. /* 50 words give you 800 horizontal pixels. An A500 can't do that, so it ought
  341.  * to be enough. */
  342. #define MAX_WORDS_PER_LINE 50
  343. static uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
  344.  
  345. /*
  346.  * The idea behind this code is that at some point during each horizontal
  347.  * line, we decide how to draw this line. There are many more-or-less
  348.  * independent decisions, each of which can be taken at a different horizontal
  349.  * position.
  350.  * Sprites, color changes and bitplane delay changes are handled specially: 
  351.  * There isn't a single decision, but a list of structures containing 
  352.  * information on how to draw the line.
  353.  */
  354.  
  355. struct color_change {
  356.     int linepos;
  357.     int regno;
  358.     unsigned long value;
  359. };
  360.  
  361. struct sprite_draw {
  362.     int linepos;
  363.     int num;
  364.     int ctl;
  365.     uae_u32 datab;
  366. };
  367.  
  368. struct delay_change {
  369.     int linepos;
  370.     unsigned int value;
  371. };
  372.  
  373. /* Way too much... */
  374. #define MAX_REG_CHANGE ((maxvpos+1) * 2 * maxhpos)
  375. static int current_change_set;
  376.  
  377. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  378. /* sam: Those arrays uses around 7Mb of BSS... That seems  */
  379. /* too much for AmigaDOS (uae crashes as soon as one loads */
  380. /* it. So I use a different strategy here (realloc the     */
  381. /* arrays when needed. That strategy might be usefull for  */
  382. /* computer with low memory.                               */
  383. static struct sprite_draw  *sprite_positions[2];
  384. static int max_sprite_draw    = 400;
  385. static int delta_sprite_draw  = 0;
  386. static struct color_change *color_changes[2];
  387. static int max_color_change   = 400;
  388. static int delta_color_change = 0;
  389. static struct delay_change *delay_changes;
  390. static int max_delay_change = 100;
  391. static int delta_delay_change = 0;
  392. #else
  393. static struct sprite_draw sprite_positions[2][MAX_REG_CHANGE];
  394. static struct color_change color_changes[2][MAX_REG_CHANGE];
  395. /* We don't remember those across frames, that would be too much effort. 
  396.  * We simply redraw the line whenever we see one of these. */
  397. static struct delay_change delay_changes[MAX_REG_CHANGE];
  398. #endif
  399. static struct sprite_draw *curr_sprite_positions, *prev_sprite_positions;
  400. static struct color_change *curr_color_changes, *prev_color_changes;
  401.  
  402. static int next_color_change, next_sprite_draw, next_delay_change;
  403.  
  404. static struct color_entry color_tables[2][(maxvpos+1) * 2];
  405. static struct color_entry *curr_color_tables, *prev_color_tables;
  406. static int next_color_entry, remembered_color_entry, drawing_color_matches;
  407. static enum { color_match_acolors, color_match_full } color_match_type;
  408. static int color_src_match, color_dest_match, color_compare_result;
  409.  
  410. static int last_redraw_point;
  411.  
  412. static int first_drawn_line, last_drawn_line;
  413. static int first_block_line, last_block_line;
  414.  
  415. static __inline__ void docols(struct color_entry *colentry)
  416. {
  417. #if AGA_CHIPSET == 0
  418.     int i;
  419.     for (i = 0; i < 32; i++)
  420.     colentry->acolors[i] = xcolors[colentry->color_regs[i]];
  421. #endif
  422. }
  423.  
  424. void notice_new_xcolors (void)
  425. {
  426.     int i;
  427.     docols(¤t_colors);
  428.     docols(&colors_for_drawing);
  429.     for (i = 0; i < (maxvpos+1)*2; i++) {
  430.     docols(color_tables[0]+i);
  431.     docols(color_tables[1]+i);
  432.     }
  433. }
  434.  
  435. void notice_screen_contents_lost (void)
  436. {
  437.     frame_redraw_necessary = 2;
  438. }
  439.  
  440. static void init_regchanges (void)
  441. {
  442.     size_t i;
  443.  
  444.     next_color_change = 0;
  445.     next_sprite_draw = 0;
  446.     current_change_set = 0;
  447.     for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
  448.     linestate[i] = LINE_UNDECIDED;
  449. }
  450.  
  451. /* struct decision contains things we save across drawing frames for
  452.  * comparison (smart update stuff). */
  453. struct decision {
  454.     unsigned long color0;
  455.     int which;
  456.     int plfstrt, plflinelen;
  457.     int diwfirstword, diwlastword;
  458.     int ctable;
  459.  
  460.     uae_u16 bplcon0, bplcon1, bplcon2;
  461. #if 0 /* We don't need this. */
  462.     uae_u16 bplcon3;
  463. #endif
  464. #if AGA_CHIPSET == 1
  465.     uae_u16 bplcon4;
  466. #endif
  467. };
  468.  
  469. /* Anything related to changes in hw registers during the DDF for one
  470.  * line. */
  471. struct draw_info {
  472.     int first_sprite_draw, last_sprite_draw;
  473.     int first_color_change, last_color_change;
  474.     int first_delay_change, last_delay_change;
  475.     int nr_color_changes, nr_sprites;
  476. };
  477.  
  478. /* These few are only needed during/at the end of the scanline, and don't
  479.  * have to be remembered. */
  480. static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes, decided_hires;
  481.  
  482. /* These are generated by the drawing code from the line_decisions array for
  483.  * each line that needs to be drawn. */
  484. static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
  485. static int bpldelay1, bpldelay2;
  486. static int plfpri[3];
  487.  
  488. static struct decision line_decisions[2 * (maxvpos+1) + 1];
  489. static struct draw_info line_drawinfo[2][2 * (maxvpos+1) + 1];
  490. static struct draw_info *curr_drawinfo, *prev_drawinfo;
  491. static struct decision *dp_for_drawing;
  492. static struct draw_info *dip_for_drawing;
  493.  
  494. static char line_changed[2 * (maxvpos+1)];
  495.  
  496. #ifdef SMART_UPDATE
  497. #define MARK_LINE_CHANGED(l) do { line_changed[l] = 1; } while (0)
  498. #else
  499. #define MARK_LINE_CHANGED(l) do { } while (0)
  500. #endif
  501.  
  502. static struct decision thisline_decision;
  503. static int modulos_added, plane_decided, color_decided, very_broken_program;
  504.  
  505. static void do_sprites(int currvp, int currhp);
  506.  
  507. static void remember_ctable (void)
  508. {
  509.     if (remembered_color_entry == -1) {
  510.     /* The colors changed since we last recorded a color map. Record a
  511.      * new one. */
  512.     memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors);
  513.     remembered_color_entry = next_color_entry++;
  514.     }
  515.     thisline_decision.ctable = remembered_color_entry;
  516.     if (color_src_match == -1 || color_dest_match != remembered_color_entry
  517.     || line_decisions[next_lineno].ctable != color_src_match)
  518.     {
  519.     /* The remembered comparison didn't help us - need to compare again. */
  520.     int oldctable = line_decisions[next_lineno].ctable;
  521.     int changed = 0;
  522.  
  523.     if (oldctable == -1) {
  524.         changed = 1;
  525.         color_src_match = color_dest_match = -1;
  526.     } else {
  527.         color_compare_result = fast_memcmp (&prev_color_tables[oldctable].color_regs, 
  528.                         ¤t_colors.color_regs,
  529.                         sizeof current_colors.color_regs) != 0;
  530.         if (color_compare_result)
  531.         changed = 1;
  532.         color_src_match = oldctable;
  533.         color_dest_match = remembered_color_entry;
  534.     }
  535.     if (changed) {
  536.         line_changed[next_lineno] = 1;
  537.     }
  538.     } else {
  539.     /* We know the result of the comparison */
  540.     if (color_compare_result)
  541.         line_changed[next_lineno] = 1;
  542.     }
  543. }
  544.  
  545. static void remember_ctable_for_border (void)
  546. {
  547.     remember_ctable ();
  548. #if 0
  549.     if (remembered_color_entry == -1) {
  550.     /* The colors changed since we last recorded a color map. Record a
  551.      * new one. */
  552.     memcpy (curr_color_tables + next_color_entry, ¤t_colors, sizeof current_colors);
  553.     remembered_color_entry = next_color_entry++;
  554.     }
  555.     thisline_decision.ctable = remembered_color_entry;
  556.     if (color_src_match == -1 || color_dest_match != remembered_color_entry
  557.     || line_decisions[next_lineno].ctable != color_src_match)
  558.     {
  559.     /* The remembered comparison didn't help us - need to compare again. */
  560.     int oldctable = line_decisions[next_lineno].ctable;
  561.     int changed = 0;
  562.  
  563.     if (oldctable == -1) {
  564.         changed = 1;
  565.         color_src_match = color_dest_match = -1;
  566.     } else {
  567.         color_compare_result = fast_memcmp (&prev_color_tables[oldctable].color_regs, 
  568.                         ¤t_colors.color_regs,
  569.                         sizeof current_colors.color_regs) != 0;
  570.         if (color_compare_result)
  571.         changed = 1;
  572.         color_src_match = oldctable;
  573.         color_dest_match = remembered_color_entry;
  574.     }
  575.     if (changed) {
  576.         line_changed[next_lineno] = 1;
  577.     }
  578.     } else {
  579.     /* We know the result of the comparison */
  580.     if (color_compare_result)
  581.         line_changed[next_lineno] = 1;
  582.     }
  583. #endif
  584. }
  585.  
  586. static void decide_diw (void)
  587. {
  588.     if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
  589.     && PIXEL_XPOS (current_hpos ()) >= diwfirstword) 
  590.     {
  591.     thisline_decision.diwfirstword = diwfirstword;
  592.     hdiwstate = DIW_waiting_stop;
  593.     /* Decide playfield delays only at DIW start, because they don't matter before and
  594.      * some programs change them after DDF start but before DIW start. */
  595.     thisline_decision.bplcon1 = bplcon1;
  596.     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
  597.         MARK_LINE_CHANGED (next_lineno);
  598.     thisline_decision.diwlastword = -1;
  599.     }
  600.     if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 
  601.     && PIXEL_XPOS (current_hpos ()) >= diwlastword)
  602.     {
  603.     thisline_decision.diwlastword = diwlastword;
  604.     hdiwstate = DIW_waiting_start;
  605.     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
  606.         MARK_LINE_CHANGED (next_lineno);
  607.     }
  608. }
  609.  
  610. static __inline__ void decide_as_playfield (int startpos, int len)
  611. {
  612.     thisline_decision.which = 1;
  613.  
  614.     /* The latter condition might be able to happen in interlaced frames. */
  615.     if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
  616.     thisframe_first_drawn_line = vpos;
  617.     thisframe_last_drawn_line = vpos;
  618.  
  619.     thisline_decision.plfstrt = startpos;
  620.     thisline_decision.plflinelen = len;
  621.  
  622.     /* These are for comparison. */
  623.     thisline_decision.bplcon0 = bplcon0;
  624.     thisline_decision.bplcon2 = bplcon2;
  625. #if AGA_CHIPSET == 1
  626.     thisline_decision.bplcon4 = bplcon4;
  627. #endif
  628.  
  629. #ifdef SMART_UPDATE
  630.     if (line_decisions[next_lineno].plfstrt != thisline_decision.plfstrt
  631.     || line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
  632.     || line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
  633.     || line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
  634. #if AGA_CHIPSET == 1
  635.     || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
  636. #endif
  637.     )
  638. #endif /* SMART_UPDATE */
  639.     line_changed[next_lineno] = 1;
  640. }
  641.  
  642. static __inline__ void post_decide_line (void)
  643. {
  644.     static int warned = 0;
  645.     int tmp;
  646.  
  647.     if (thisline_decision.which == 1 && current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen
  648.     && ((bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE)))
  649.     {
  650.     /* This is getting gross... */
  651.     thisline_decision.plflinelen = current_hpos() - thisline_decision.plfstrt;
  652.     thisline_decision.plflinelen &= 7;
  653.     if (thisline_decision.plflinelen == 0)
  654.         thisline_decision.which = -1;
  655.     /* ... especially THIS! */
  656.     modulos_added = 1;
  657.     return;
  658.     }
  659.     
  660.     if (thisline_decision.which != -1 || diwstate == DIW_waiting_start || (bplcon0 & 0x7000) == 0
  661.     || !dmaen (DMA_BITPLANE) || current_hpos () >= thisline_decision.plfstrt + thisline_decision.plflinelen)
  662.     return;
  663. #if 0 /* Can't warn because Kickstart 1.3 does it at reset time ;-) */
  664.     if (!warned) {
  665.     write_log ("That program you are running is _really_ broken.\n");
  666.     warned = 1;
  667.     }
  668. #endif
  669.  
  670.     decided_hires = (bplcon0 & 0x8000) == 0x8000;
  671.     decided_nr_planes = nr_planes_from_bplcon0;
  672.  
  673.     /* Magic 12, Ray of Hope 2 demo does ugly things. Looks great from the
  674.      * outside, rotten inside. */
  675.     if (decided_hires) {
  676.     tmp = current_hpos () & ~3;
  677.     very_broken_program = current_hpos () & 3;
  678.     } else {
  679.     tmp = current_hpos () & ~7;
  680.     very_broken_program = current_hpos () & 7;
  681.     }
  682.     MARK_LINE_CHANGED (next_lineno); /* Play safe. */
  683.     decide_as_playfield (tmp, plflinelen + plfstrt - tmp);
  684. }
  685.  
  686. static void decide_line_1 (void)
  687. {
  688.     do_sprites(vpos, current_hpos ());
  689.  
  690.     /* Surprisingly enough, this seems to be correct here - putting this into
  691.      * decide_diw() results in garbage. */
  692.     if (diwstate == DIW_waiting_start && vpos == plffirstline) {
  693.     diwstate = DIW_waiting_stop;
  694.     calculate_copper_cycle_time ();
  695.     }
  696.     if (diwstate == DIW_waiting_stop && vpos == plflastline) {
  697.     diwstate = DIW_waiting_start;
  698.     calculate_copper_cycle_time ();
  699.     }
  700.  
  701.     if (framecnt != 0) {
  702. /*    thisline_decision.which = -2; This doesn't do anything but hurt, I think. */
  703.     return;
  704.     }
  705.  
  706.     if (!dmaen(DMA_BITPLANE) || diwstate == DIW_waiting_start || nr_planes_from_bplcon0 == 0) {
  707.     /* We don't want to draw this one. */
  708.     thisline_decision.which = -1;
  709.     thisline_decision.plfstrt = plfstrt;
  710.     thisline_decision.plflinelen = plflinelen;
  711.     return;
  712.     }
  713.  
  714.     decided_hires = (bplcon0 & 0x8000) == 0x8000;
  715.     decided_nr_planes = nr_planes_from_bplcon0;
  716. #if 0
  717.     /* The blitter gets slower if there's high bitplane activity. 
  718.      * @@@ but the values must be different. FIXME */
  719.     if (bltstate != BLT_done
  720.     && ((decided_hires && decided_nr_planes > 2)
  721.         || (!decided_hires && decided_nr_planes > 4)))
  722.     {
  723.     int pl = decided_nr_planes;
  724.     unsigned int n = (eventtab[ev_blitter].evtime-cycles);
  725.     if (n > plflinelen)
  726.         n = plflinelen;
  727.     n >>= 1;
  728.     if (decided_hires)
  729.         pl <<= 1;
  730.     if (pl == 8)
  731.         eventtab[ev_blitter].evtime += plflinelen;
  732.     else if (pl == 6)
  733.         eventtab[ev_blitter].evtime += n*2;
  734.     else if (pl == 5)
  735.         eventtab[ev_blitter].evtime += n*3/2;
  736.     events_schedule();
  737.     }
  738. #endif
  739.     decide_as_playfield (plfstrt, plflinelen);
  740. }
  741.  
  742. static __inline__ void decide_line (void)
  743. {
  744.     if (thisline_decision.which == 0 && current_hpos() >= plfstrt)
  745.     decide_line_1 ();
  746. }
  747.  
  748. static void record_color_change (int regno, unsigned long value)
  749. {
  750.     /* Early positions don't appear on-screen. */
  751.     if (framecnt != 0 || vpos < minfirstline || current_hpos () < 0x18
  752.     /*|| currprefs.emul_accuracy == 0*/)
  753.     return;
  754.  
  755.     decide_diw ();
  756.     decide_line ();
  757.  
  758.     /* See if we can record the color table, but have not done so yet.
  759.      * @@@ There might be a minimal performance loss in case someone changes
  760.      * a color exactly at the start of the DIW. I don't think it can actually
  761.      * fail to work even in this case, but I'm not 100% sure.
  762.      * @@@ There might be a slightly larger performance loss if we're drawing
  763.      * this line as border... especially if there are changes in colors != 0
  764.      * we might end up setting line_changed for no reason. FIXME */
  765.     if (thisline_decision.diwfirstword >= 0) {
  766.     if (thisline_decision.ctable == -1)
  767.         remember_ctable ();
  768.     }
  769.  
  770.     /* Changes outside the DIW can be ignored if the modified color is not the
  771.      * background color, or if the accuracy is < 2. */
  772.     if ((regno != 0 || currprefs.emul_accuracy < 2)
  773.     && (diwstate == DIW_waiting_start || thisline_decision.diwfirstword < 0
  774.         || thisline_decision.diwlastword >= 0
  775.         || thisline_decision.which == 0
  776.         || (thisline_decision.which == 1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)))
  777.     return;
  778.     
  779.     /* If the border is changed the first time before the DIW, record the
  780.      * original starting border value. */
  781.     if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) {
  782.     thisline_decision.color0 = current_colors.color_regs[0];
  783.     if (line_decisions[next_lineno].color0 != value)
  784.         line_changed[next_lineno] = 1;
  785.     }
  786.     /* Anything else gets recorded in the color_changes table. */
  787. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  788.     if(next_color_change >= max_color_change) {
  789.         ++delta_color_change;
  790.     return;
  791.     }
  792. #endif
  793.     curr_color_changes[next_color_change].linepos = current_hpos ();
  794.     curr_color_changes[next_color_change].regno = regno;
  795.     curr_color_changes[next_color_change++].value = value;
  796. }
  797.  
  798. static void decide_delay (void)
  799. {
  800.     static int warned;
  801.  
  802.     /* Don't do anything if we're outside the DIW. */
  803.     if (thisline_decision.diwfirstword == -1 || thisline_decision.diwlastword > 0)
  804.     return;
  805.     decide_line ();
  806.     /* Half-hearted attempt to get things right even when post_decide_line() changes
  807.      * the decision afterwards. */
  808.     if (thisline_decision.which != 1) {
  809.     thisline_decision.bplcon1 = bplcon1;
  810.     return;
  811.     }
  812.     /* @@@ Could check here for DDF stopping earlier than DIW */
  813.     
  814. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  815.     if(next_delay_change >= max_delay_change) {
  816.         ++delta_delay_change;
  817.     return;
  818.     }
  819. #endif
  820.     delay_changes[next_delay_change].linepos = current_hpos ();
  821.     delay_changes[next_delay_change++].value = bplcon1;
  822.     if (!warned) {
  823.     warned = 1;
  824.     write_log ("Program is torturing BPLCON1.\n");
  825.     }
  826. }
  827.  
  828. /*
  829.  * The decision which bitplane pointers to use is not taken at plfstrt, since
  830.  * data fetch does not start for all planes at this point. Therefore, we wait
  831.  * for the end of the ddf area or the first write to any of the bitplane
  832.  * pointer registers, whichever comes last, before we decide which plane pointers
  833.  * to use.
  834.  * Call decide_line() before this function.
  835.  */
  836. static void decide_plane (void)
  837. {
  838.     int i, bytecount;
  839.  
  840.     if (framecnt != 0 || plane_decided)
  841.     return;
  842.  
  843.     if (decided_nr_planes == -1 /* Still undecided */
  844.     || current_hpos () < thisline_decision.plfstrt + thisline_decision.plflinelen)
  845.     return;
  846.  
  847.     plane_decided = 1;
  848.  
  849.     bytecount = plflinelen / (decided_hires ? 4 : 8) * 2;
  850.  
  851.     if (bytecount > MAX_WORDS_PER_LINE * 2) {
  852.     /* Can't happen. */
  853.     static int warned = 0;
  854.     if (!warned)
  855.         write_log ("Mysterious bug in decide_plane(). Please report.\n");
  856.     bytecount = 0;
  857.     }
  858.     if (!very_broken_program) {
  859.     uae_u8 *dataptr = line_data[next_lineno];
  860.     for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
  861.         uaecptr pt = bplpt[i];
  862.         uae_u8 *real_ptr = pfield_xlateptr(pt, bytecount);
  863.         if (real_ptr == NULL)
  864.         real_ptr = pfield_xlateptr(0, 0);
  865. #ifdef SMART_UPDATE
  866. #if 1
  867.         if (line_changed[next_lineno])
  868.         memcpy (dataptr, real_ptr, bytecount);
  869.         else
  870. #endif
  871.         line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
  872. #else
  873.         real_bplpt[i] = real_ptr;
  874. #endif
  875.     }
  876.     } else {
  877.     uae_u8 *dataptr = line_data[next_lineno];
  878.     for (i = 0; i < decided_nr_planes; i++, dataptr += MAX_WORDS_PER_LINE*2) {
  879.         uaecptr pt = bplpt[i];
  880.         uae_u8 *real_ptr;
  881.         
  882.         if (decided_hires) {
  883.         switch (i) {
  884.          case 3: pt -= 2;
  885.          case 2: pt -= (very_broken_program >= 3 ? 2 : 0); break;
  886.          case 1: pt -= (very_broken_program >= 2 ? 2 : 0); break;
  887.          case 0: break;
  888.         }
  889.         } else {
  890.         switch (i) {
  891.          case 5: pt -= (very_broken_program >= 3 ? 2 : 0); break;
  892.          case 4: pt -= (very_broken_program >= 7 ? 2 : 0); break;
  893.          case 3: pt -= (very_broken_program >= 2 ? 2 : 0); break;
  894.          case 2: pt -= (very_broken_program >= 6 ? 2 : 0); break;
  895.          case 1: pt -= (very_broken_program >= 4 ? 2 : 0); break;
  896.          case 0: break;
  897.         }
  898.         }
  899.         real_ptr = pfield_xlateptr(pt, bytecount);
  900.         if (real_ptr == NULL)
  901.         real_ptr = pfield_xlateptr(0, 0);
  902. #ifdef SMART_UPDATE
  903.         if (!line_changed[next_lineno])
  904.         line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount);
  905.         else
  906.         memcpy (dataptr, real_ptr, bytecount);
  907. #else
  908.         real_bplpt[i] = real_ptr;
  909. #endif
  910.     }
  911.     }
  912. }
  913.  
  914. /*
  915.  * Called from the BPLxMOD routines, after a new value has been written.
  916.  * This routine decides whether the new value is already relevant for the
  917.  * current line.
  918.  */
  919. static void decide_modulos (void)
  920. {
  921.     /* All this effort just for the Sanity WOC demo... */
  922.     decide_line ();
  923.     if (decided_nr_planes != -1 && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
  924.     return;
  925.     decided_bpl1mod = bpl1mod;
  926.     decided_bpl2mod = bpl2mod;
  927. }
  928.  
  929. /*
  930.  * Call decide_plane() before calling this.
  931.  */
  932. static void do_modulos (void)
  933. {
  934.     /* decided_nr_planes is != -1 if this line should be drawn by the
  935.      * display hardware, regardless of whether it fits on the emulated screen. 
  936.      */
  937.     if (decided_nr_planes != -1 && plane_decided && !modulos_added
  938.     && current_hpos() >= thisline_decision.plfstrt + thisline_decision.plflinelen)
  939.     {
  940.     int bytecount = thisline_decision.plflinelen / (decided_hires ? 4 : 8) * 2;
  941.     int add1 = bytecount + decided_bpl1mod;
  942.     int add2 = bytecount + decided_bpl2mod;
  943.  
  944.     if (!very_broken_program) {
  945.         switch (decided_nr_planes) {
  946.          case 8: bplpt[7] += add2;
  947.          case 7: bplpt[6] += add1;
  948.          case 6: bplpt[5] += add2;
  949.          case 5: bplpt[4] += add1;
  950.          case 4: bplpt[3] += add2;
  951.          case 3: bplpt[2] += add1;
  952.          case 2: bplpt[1] += add2;
  953.          case 1: bplpt[0] += add1;
  954.         }
  955.     } else if (bplhires) {
  956.         switch (decided_nr_planes) {
  957.          case 8: bplpt[7] += add2;
  958.          case 7: bplpt[6] += add1;
  959.          case 6: bplpt[5] += add2;
  960.          case 5: bplpt[4] += add1;
  961.          case 4: bplpt[3] += add2 - 2;
  962.          case 3: bplpt[2] += add1 - (very_broken_program >= 3 ? 2 : 0);
  963.          case 2: bplpt[1] += add2 - (very_broken_program >= 2 ? 2 : 0);
  964.          case 1: bplpt[0] += add1;
  965.          }
  966.     } else {
  967.         switch (decided_nr_planes) {
  968.          case 8: bplpt[7] += add2;
  969.          case 7: bplpt[6] += add1;
  970.          case 6: bplpt[5] += add2 - (very_broken_program >= 3 ? 2 : 0);
  971.          case 5: bplpt[4] += add1 - (very_broken_program >= 7 ? 2 : 0);
  972.          case 4: bplpt[3] += add2 - (very_broken_program >= 2 ? 2 : 0);
  973.          case 3: bplpt[2] += add1 - (very_broken_program >= 6 ? 2 : 0);
  974.          case 2: bplpt[1] += add2 - (very_broken_program >= 4 ? 2 : 0);
  975.          case 1: bplpt[0] += add1;
  976.          }
  977.     }
  978.  
  979.     modulos_added = 1;
  980.     }
  981. }
  982.  
  983. static __inline__ void record_sprite (int spr, int sprxp)
  984. {
  985.     int pos = next_sprite_draw;
  986.     unsigned int data, datb;
  987.  
  988. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  989.     if(pos >= max_sprite_draw) {
  990.         ++delta_sprite_draw;
  991.         return;
  992.     }
  993. #endif
  994.     data = sprdata[spr];
  995.     datb = sprdatb[spr];
  996.  
  997.     /* XXX FIXME, this isn't very clever, but it might do */
  998.     for (;;) {
  999.     if (pos == curr_drawinfo[next_lineno].first_sprite_draw)
  1000.         break;
  1001.     if (curr_sprite_positions[pos-1].linepos < sprxp)
  1002.         break;
  1003.     if (curr_sprite_positions[pos-1].linepos == sprxp
  1004.         && curr_sprite_positions[pos-1].num > spr)
  1005.         break;
  1006.     printf("Foo\n");
  1007.     pos--;
  1008.     }
  1009.     if (pos != next_sprite_draw) {
  1010.     int pos2 = next_sprite_draw;
  1011.     while (pos2 != pos) {
  1012.         curr_sprite_positions[pos2] = curr_sprite_positions[pos2-1];
  1013.         pos2--;
  1014.     }
  1015.     }
  1016.     curr_sprite_positions[pos].linepos = sprxp;
  1017.     curr_sprite_positions[pos].num = spr;
  1018.     curr_sprite_positions[pos].ctl = sprctl[spr];
  1019.     curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8]
  1020.                     | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]);
  1021.     next_sprite_draw++;
  1022. }
  1023.  
  1024. static void decide_sprites (void)
  1025. {
  1026.     int nrs[8], posns[8], count, i;
  1027.     int point = PIXEL_XPOS (current_hpos ());
  1028.  
  1029.     if (framecnt != 0 || current_hpos() < 0x14 || nr_armed == 0 || point == last_sprite_point)
  1030.     return;
  1031.  
  1032.     decide_diw ();
  1033.     decide_line ();
  1034.  
  1035.     if (thisline_decision.which != 1)
  1036.     return;
  1037.  
  1038.     count = 0;
  1039.     for (i = 0; i < 8; i++) {
  1040.     int sprxp = sprxpos[i];
  1041.     int j, bestp;
  1042.     
  1043.     if (!sprarmed[i] || sprxp < 0 || sprxp > point || last_sprite_point >= sprxp)
  1044.         continue;
  1045.     if ((thisline_decision.diwfirstword >= 0 && sprxp + sprite_width < thisline_decision.diwfirstword)
  1046.         || (thisline_decision.diwlastword >= 0 && sprxp > thisline_decision.diwlastword))
  1047.         continue;
  1048.     
  1049.     for (bestp = 0; bestp < count; bestp++) {
  1050.         if (posns[bestp] > sprxp)
  1051.         break;
  1052.         if (posns[bestp] == sprxp && nrs[bestp] < i)
  1053.         break;
  1054.     }
  1055.     for (j = count; j > bestp; j--) {
  1056.         posns[j] = posns[j-1];
  1057.         nrs[j] = nrs[j-1];
  1058.     }
  1059.     posns[j] = sprxp;
  1060.     nrs[j] = i;
  1061.     count++;
  1062.     }
  1063.     for (i = 0; i < count; i++)
  1064.     record_sprite(nrs[i], posns[i]);
  1065.     last_sprite_point = point;
  1066. }
  1067.  
  1068. static void finish_decisions (void)
  1069. {
  1070.     struct draw_info *dip;
  1071.     struct draw_info *dip_old;
  1072.     struct decision *dp;
  1073.     int changed;
  1074.  
  1075.     if (framecnt != 0)
  1076.     return;
  1077.  
  1078.     decide_diw ();
  1079.     if (thisline_decision.which == 0)
  1080.     decide_line_1 ();
  1081.  
  1082.     if (hdiwstate == DIW_waiting_stop) {
  1083.     thisline_decision.diwlastword = max_diwlastword;
  1084.     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
  1085.         MARK_LINE_CHANGED (next_lineno);
  1086.     }
  1087.  
  1088.     if (line_decisions[next_lineno].which != thisline_decision.which)
  1089.     line_changed[next_lineno] = 1;
  1090.     decide_plane ();
  1091.  
  1092.     dip = curr_drawinfo + next_lineno;
  1093.     dip_old = prev_drawinfo + next_lineno;
  1094.     dp = line_decisions + next_lineno;
  1095.     changed = line_changed[next_lineno];
  1096.  
  1097.     if (thisline_decision.which == 1) {
  1098.     if (diwlastword > max_diwstop)
  1099.         max_diwstop = diwlastword;
  1100.     if (diwfirstword < min_diwstart)
  1101.         min_diwstart = diwfirstword;
  1102.  
  1103.     decide_sprites();
  1104.  
  1105.     if (thisline_decision.bplcon1 != line_decisions[next_lineno].bplcon1)
  1106.         changed = 1;
  1107.     }
  1108.  
  1109.     dip->last_color_change = next_color_change;
  1110.     dip->last_delay_change = next_delay_change;
  1111.     dip->last_sprite_draw = next_sprite_draw;
  1112.     
  1113.     if (thisline_decision.ctable == -1) {
  1114.     if (thisline_decision.which == 1)
  1115.         remember_ctable ();
  1116.     else
  1117.         remember_ctable_for_border ();
  1118.     }
  1119.     if (thisline_decision.which == -1 && thisline_decision.color0 == 0xFFFFFFFFul)
  1120.     thisline_decision.color0 = current_colors.color_regs[0];
  1121.  
  1122.     dip->nr_color_changes = next_color_change - dip->first_color_change;
  1123.     dip->nr_sprites = next_sprite_draw - dip->first_sprite_draw;
  1124.  
  1125.     if (dip->first_delay_change != dip->last_delay_change)
  1126.     changed = 1;
  1127.     if (!changed
  1128.     && (dip->nr_color_changes != dip_old->nr_color_changes
  1129.         || (dip->nr_color_changes > 0 
  1130.         && fast_memcmp (curr_color_changes + dip->first_color_change,
  1131.                 prev_color_changes + dip_old->first_color_change,
  1132.                 dip->nr_color_changes * sizeof *curr_color_changes) != 0)))
  1133.     changed = 1;
  1134.     if (!changed && thisline_decision.which == 1
  1135.     && (dip->nr_sprites != dip_old->nr_sprites
  1136.         || (dip->nr_sprites > 0
  1137.         && fast_memcmp (curr_sprite_positions + dip->first_sprite_draw,
  1138.                 prev_sprite_positions + dip_old->first_sprite_draw,
  1139.                 dip->nr_sprites * sizeof *curr_sprite_positions) != 0)))
  1140.     changed = 1;
  1141.  
  1142.     if (changed) {
  1143.     line_changed[next_lineno] = 1;
  1144.     *dp = thisline_decision;
  1145.     } else
  1146.     /* The only one that may differ: */
  1147.     dp->ctable = thisline_decision.ctable;
  1148. }
  1149.  
  1150. static void reset_decisions (void)
  1151. {
  1152.     if (framecnt != 0)
  1153.     return;
  1154.     thisline_decision.which = 0;
  1155.     decided_bpl1mod = bpl1mod;
  1156.     decided_bpl2mod = bpl2mod;
  1157.     decided_nr_planes = -1;
  1158.  
  1159.     /* decided_hires shouldn't be touched before it's initialized by decide_line(). */
  1160.     thisline_decision.diwfirstword = -1;
  1161.     thisline_decision.diwlastword = -2;
  1162.     if (hdiwstate == DIW_waiting_stop) {
  1163.     thisline_decision.diwfirstword = PIXEL_XPOS (DISPLAY_LEFT_SHIFT/2);
  1164.     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
  1165.         MARK_LINE_CHANGED (next_lineno);
  1166.     }
  1167.     thisline_decision.ctable = -1;
  1168.     thisline_decision.color0 = 0xFFFFFFFFul;
  1169.  
  1170.     line_changed[next_lineno] = 0;
  1171.     curr_drawinfo[next_lineno].first_color_change = next_color_change;
  1172.     curr_drawinfo[next_lineno].first_delay_change = next_delay_change;
  1173.     curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw;
  1174.  
  1175.     /*memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at);*/
  1176.     last_sprite_point = 0;
  1177.     modulos_added = 0;
  1178.     plane_decided = 0;
  1179.     color_decided = 0;
  1180.     very_broken_program = 0;
  1181. }
  1182.  
  1183. static void init_decisions (void)
  1184. {
  1185.     size_t i;
  1186.     for (i = 0; i < sizeof line_decisions / sizeof *line_decisions; i++) {
  1187.     line_decisions[i].which = -2;
  1188.     }
  1189. }
  1190.  
  1191. static void calcdiw (void)
  1192. {
  1193.     diwfirstword = ((diwstrt & 0xFF) - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
  1194.     diwlastword  = ((diwstop & 0xFF) + 0x100 - DISPLAY_LEFT_SHIFT - 1) << lores_shift;
  1195.  
  1196.     if (diwlastword > max_diwlastword)
  1197.     diwlastword = max_diwlastword;
  1198.     if (diwfirstword < 0)
  1199.     diwfirstword = 0;
  1200.     if (diwlastword < 0)
  1201.     diwlastword = 0;
  1202.     
  1203.     plffirstline = diwstrt >> 8;
  1204.     plflastline = diwstop >> 8;
  1205. #if 0
  1206.     /* This happens far too often. */
  1207.     if (plffirstline < minfirstline) {
  1208.     fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
  1209.     plffirstline = minfirstline;
  1210.     }
  1211. #endif
  1212.     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
  1213. #if 0 /* Turrican does this */
  1214.     if (plflastline > 313) {
  1215.     fprintf(stderr, "Warning: Playfield out of range!\n");
  1216.     plflastline = 313;
  1217.     }
  1218. #endif
  1219.     plfstrt = ddfstrt;
  1220.     plfstop = ddfstop;
  1221.     if (plfstrt < 0x18) plfstrt = 0x18;
  1222.     if (plfstop < 0x18) plfstop = 0x18;
  1223.     if (plfstop > 0xD8) plfstop = 0xD8;
  1224.     if (plfstrt > plfstop) plfstrt = plfstop;
  1225.  
  1226.     /* ! If the masking operation is changed, the pfield_doline code could break
  1227.      * on some systems (alignment) */
  1228.     /* This actually seems to be correct now, at least the non-AGA stuff... */
  1229.     plfstrt &= ~3;
  1230.     plfstop &= ~3;
  1231.     /* @@@ Start looking for AGA bugs here... (or maybe even in the above masking ops) */
  1232.     if ((fmode & 3) == 0)
  1233.     plflinelen = (plfstop-plfstrt+15) & ~7;
  1234.     else if ((fmode & 3) == 3)
  1235.     plflinelen = (plfstop-plfstrt+63) & ~31;
  1236.     else
  1237.     plflinelen = (plfstop-plfstrt+31) & ~15;
  1238. }
  1239.  
  1240. /*
  1241.  * Screen update macros/functions
  1242.  */
  1243.  
  1244. static unsigned int ham_lastcolor;
  1245.  
  1246. static void init_ham_decoding(int first)
  1247. {
  1248.     int pix = dp_for_drawing->diwfirstword;
  1249.     ham_lastcolor = colors_for_drawing.color_regs[0];
  1250.     while (pix < first) {
  1251.     int pv = pixdata.apixels[pix];
  1252.     switch(pv & 0x30) {
  1253.      case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
  1254.      case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
  1255.      case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
  1256.      case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
  1257.     }
  1258.     pix++;
  1259.     }
  1260. }
  1261.  
  1262. static void decode_ham6 (int pix, int stoppos)
  1263. {
  1264.     uae_u32 *buf = ham_linebuf; 
  1265.  
  1266.     if (!bplham || bplplanecnt != 6)
  1267.     return;
  1268.     
  1269.     if (stoppos > dp_for_drawing->diwlastword)
  1270.     stoppos = dp_for_drawing->diwlastword;
  1271.     if (pix < dp_for_drawing->diwfirstword) {
  1272.     ham_lastcolor = colors_for_drawing.color_regs[0];
  1273.     pix = dp_for_drawing->diwfirstword;
  1274.     }
  1275. #ifdef LORES_HACK
  1276.     if (currprefs.gfx_lores == 2)
  1277.     pix <<= 1, stoppos <<= 1;
  1278. #endif
  1279.     while (pix < stoppos) {
  1280.     int pv = pixdata.apixels[pix];
  1281.     switch(pv & 0x30) {
  1282.      case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
  1283.      case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
  1284.      case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
  1285.      case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
  1286.     }
  1287.  
  1288.     buf[pix++] = ham_lastcolor;
  1289.     }    
  1290. }
  1291. #if 0
  1292. static void decode_ham_aga (int pix, int stoppos)
  1293. {
  1294.     static uae_u32 lastcolor;
  1295.     uae_u32 *buf = ham_linebuf; 
  1296.  
  1297.     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
  1298.     return;
  1299.     
  1300.     if (pix <= dp_for_drawing->diwfirstword) {
  1301.     pix = dp_for_drawing->diwfirstword;
  1302.     lastcolor = colors_for_drawing.color_regs[0];
  1303.     }
  1304.  
  1305.     if (dp_for_drawing->bplplanecnt == 6) {
  1306.     /* HAM 6 */
  1307.     while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
  1308.         int pv = pixdata.apixels[pix];
  1309.         switch(pv & 0x30) {
  1310.          case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
  1311.          case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
  1312.          case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
  1313.          case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
  1314.         }        
  1315.         buf[pix++] = lastcolor;
  1316.     }
  1317.     } else if (dp_for_drawing->bplplanecnt == 8) {
  1318.     /* HAM 8 */
  1319.     while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
  1320.         int pv = pixdata.apixels[pix];
  1321.         switch(pv & 0x3) {
  1322.          case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
  1323.          case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
  1324.          case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
  1325.          case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
  1326.         }
  1327.         buf[pix++] = lastcolor;
  1328.     }
  1329.     }
  1330. }
  1331. #endif
  1332.  
  1333. #if AGA_CHIPSET != 0
  1334. /* WARNING: Not too much of this will work correctly yet. */
  1335.  
  1336. static void pfield_linetoscr_aga(int pix, int stoppos)
  1337. {
  1338.     uae_u32 *buf = aga_lbufptr;
  1339.     int i;
  1340.     int xor = (uae_u8)(bplcon4 >> 8);
  1341.     int oldpix = pix; \
  1342.  
  1343.     buf -= pix; \
  1344.  
  1345.     for (i = 0; i < stoppos; i++)
  1346.     pixdata.apixels[i] ^= xor;
  1347.     
  1348.     while (pix < diwfirstword && pix < stoppos) {
  1349.     buf[pix++] = colors_for_drawing.color_regs[0];
  1350.     }
  1351.     if (bplham) {
  1352.     while (pix < diwlastword && pix < stoppos) {
  1353.         uae_u32 d = ham_linebuf[pix];
  1354.         buf[pix] = d;
  1355.         pix++;
  1356.     }
  1357.     } else if (bpldualpf) {
  1358.     /* Dual playfield */
  1359.     int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
  1360.     int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
  1361.     while (pix < diwlastword && pix < stoppos) {
  1362.         int pixcol = pixdata.apixels[pix];
  1363.         int pfno = lookup_no[pixcol];
  1364.         
  1365.         if (spixstate[pix]) {
  1366.             buf[pix] = colors_for_drawing.color_regs[pixcol];
  1367.         } else {
  1368.         int val = lookup[pixdata.apixels[pix]];
  1369.         if (pfno == 2) 
  1370.             val += dblpfofs[(bplcon2 >> 10) & 7];
  1371.         buf[pix] = colors_for_drawing.color_regs[val];
  1372.         }
  1373.         pix++;
  1374.     }
  1375.     } else if (bplehb) {
  1376.     while (pix < diwlastword && pix < stoppos) {
  1377.             int pixcol = pixdata.apixels[pix];
  1378.         uae_u32 d = colors_for_drawing.color_regs[pixcol];
  1379.         /* What about sprites? */
  1380.         if (pixcol & 0x20)
  1381.         d = (d & 0x777777) >> 1;
  1382.         buf[pix] = d;
  1383.         pix++;
  1384.     }
  1385.     } else {
  1386.     while (pix < diwlastword && pix < stoppos) {
  1387.         int pixcol = pixdata.apixels[pix];
  1388.         buf[pix] = colors_for_drawing.color_regs[pixcol];
  1389.         pix++;
  1390.     }
  1391.     }
  1392.     while (pix < stoppos) {
  1393.     buf[pix++] = colors_for_drawing.color_regs[0];
  1394.     }
  1395.     aga_lbufptr += pix - oldpix;
  1396. }
  1397.  
  1398. static void aga_translate32(int start, int stop)
  1399. {
  1400.     memcpy (((uae_u32 *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start));
  1401. }
  1402.  
  1403. static void aga_translate16(int start, int stop)
  1404. {
  1405.     int i;
  1406.     for (i = start; i < stop; i++) {
  1407.     uae_u32 d = aga_linebuf[i];
  1408.     uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
  1409.     ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
  1410.     }
  1411. }
  1412.  
  1413. static void aga_translate8(int start, int stop)
  1414. {
  1415.     int i;
  1416.     for (i = start; i < stop; i++) {
  1417.     uae_u32 d = aga_linebuf[i];
  1418.     uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
  1419.     ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
  1420.     }
  1421. }
  1422. #endif
  1423.  
  1424. static int linetoscr_double_offset;
  1425.  
  1426. #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE) \
  1427. static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
  1428. { \
  1429.     TYPE *buf = ((TYPE *)xlinebuffer); \
  1430.     int oldpix = pix; \
  1431.     /* These are different for register-allocation purposes. */ \
  1432.     TYPE d1, d2; \
  1433.     int offset; \
  1434. \
  1435.     if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
  1436. \
  1437.     d1 = colors_for_drawing.acolors[0]; \
  1438.     while (pix < lframe_end) { \
  1439.     buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
  1440.     pix++; \
  1441.     } \
  1442.     if (bplham && bplplanecnt == 6) { \
  1443.     /* HAM 6 */ \
  1444.     while (pix < diw_end) { \
  1445.         TYPE d = xcolors[ham_linebuf[pix]]; \
  1446.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1447.         pix++; \
  1448.     } \
  1449.     } else if (bpldualpf) { \
  1450.     /* Dual playfield */ \
  1451.     int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
  1452.     while (pix < diw_end) { \
  1453.         int pixcol = pixdata.apixels[pix]; \
  1454.         TYPE d; \
  1455.         d = colors_for_drawing.acolors[lookup[pixcol]]; \
  1456.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1457.         pix++; \
  1458.     } \
  1459.     } else if (bplehb) { \
  1460.     while (pix < diw_end) { \
  1461.         int p = pixdata.apixels[pix]; \
  1462.         TYPE d = colors_for_drawing.acolors[p]; \
  1463.         if (p >= 32) d = xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]; \
  1464.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1465.         pix++; \
  1466.     } \
  1467.     } else { \
  1468.     while (pix < diw_end) { \
  1469.         TYPE d = colors_for_drawing.acolors[pixdata.apixels[pix]]; \
  1470.         buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
  1471.         pix++; \
  1472.     } \
  1473.     } \
  1474.     d2 = colors_for_drawing.acolors[0]; \
  1475.     while (pix < stoppos) { \
  1476.     buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
  1477.     pix++; \
  1478.     } \
  1479. }
  1480.  
  1481. #define FILL_LINE(NAME, TYPE) \
  1482. static void NAME(char *buf, int start, int stop) \
  1483. { \
  1484.     TYPE *b = (TYPE *)buf; \
  1485.     int i;\
  1486.     xcolnr col = colors_for_drawing.acolors[0]; \
  1487.     for (i = start; i < stop; i++) \
  1488.         b[i] = col; \
  1489. }
  1490.  
  1491. #ifdef __mac__
  1492.  
  1493. static void inline pfield_linetoscr_8(int pix, int lframe_end, int diw_end, int stoppos)
  1494. {
  1495.     uae_u8 *buf = ((uae_u8 *)xlinebuffer);
  1496.     int oldpix = pix;
  1497.     /* These are different for register-allocation purposes. */
  1498.     uae_u8 d1, d2;
  1499.     //int offset;
  1500.     
  1501.     d1 = ~colors_for_drawing.acolors[0];
  1502.     while (pix < lframe_end) {
  1503.     buf[pix] = d1;
  1504.     pix++;
  1505.     }
  1506.     if (bplham && bplplanecnt == 6) {
  1507.     /* HAM 6 */
  1508.     while (pix < diw_end) {
  1509.         uae_u8 d = ~xcolors[ham_linebuf[pix]];
  1510.         buf[pix] = d;
  1511.         pix++;
  1512.     }
  1513.     } else if (bpldualpf) {
  1514.     /* Dual playfield */
  1515.     int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
  1516.     while (pix < diw_end) {
  1517.         int pixcol = pixdata.apixels[pix];
  1518.         uae_u8 d;
  1519.         d = ~colors_for_drawing.acolors[lookup[pixcol]];
  1520.         buf[pix] = d;
  1521.         pix++;
  1522.     }
  1523.     } else if (bplehb) {
  1524.     while (pix < diw_end) {
  1525.         int p = pixdata.apixels[pix];
  1526.         uae_u8 d = ~colors_for_drawing.acolors[p];
  1527.         if (p >= 32) d = ~(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]);
  1528.         buf[pix] = d;
  1529.         pix++;
  1530.     }
  1531.     } else {
  1532.     while (pix < diw_end) {
  1533.         uae_u8 d = ~colors_for_drawing.acolors[pixdata.apixels[pix]];
  1534.         buf[pix] = d;
  1535.         pix++;
  1536.     }
  1537.     }
  1538.     d2 = ~colors_for_drawing.acolors[0];
  1539.     while (pix < stoppos) {
  1540.     buf[pix] = d2;
  1541.     pix++;
  1542.     }
  1543. }
  1544.  
  1545. static void inline pfield_linetoscr_8_double_slow(int pix, int lframe_end, int diw_end, int stoppos)
  1546. {
  1547.     uae_u8 *buf = ((uae_u8 *)xlinebuffer);
  1548.     int oldpix = pix;
  1549.     /* These are different for register-allocation purposes. */
  1550.     uae_u8 d1, d2;
  1551.     int offset;
  1552.  
  1553.     offset = linetoscr_double_offset / sizeof(uae_u8);
  1554.     
  1555.     d1 = ~colors_for_drawing.acolors[0];
  1556.     while (pix < lframe_end) {
  1557.     buf[pix] = d1;
  1558.     buf[pix+offset] = d1;
  1559.     pix++;
  1560.     }
  1561.     if (bplham && bplplanecnt == 6) {
  1562.     /* HAM 6 */
  1563.     while (pix < diw_end) {
  1564.         uae_u8 d = ~xcolors[ham_linebuf[pix]];
  1565.         buf[pix] = d;
  1566.         buf[pix+offset] = d;
  1567.         pix++;
  1568.     }
  1569.     } else if (bpldualpf) {
  1570.     /* Dual playfield */
  1571.     int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1;
  1572.     while (pix < diw_end) {
  1573.         int pixcol = pixdata.apixels[pix];
  1574.         uae_u8 d;
  1575.         d = ~colors_for_drawing.acolors[lookup[pixcol]];
  1576.         buf[pix] = d;
  1577.         buf[pix+offset] = d;
  1578.         pix++;
  1579.     }
  1580.     } else if (bplehb) {
  1581.     while (pix < diw_end) {
  1582.         int p = pixdata.apixels[pix];
  1583.         uae_u8 d = ~colors_for_drawing.acolors[p];
  1584.         if (p >= 32) d = ~(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]);
  1585.         buf[pix] = d;
  1586.         buf[pix+offset] = d;
  1587.         pix++;
  1588.     }
  1589.     } else {
  1590.     while (pix < diw_end) {
  1591.         uae_u8 d = ~colors_for_drawing.acolors[pixdata.apixels[pix]];
  1592.         buf[pix] = d;
  1593.         buf[pix+offset] = d;
  1594.         pix++;
  1595.     }
  1596.     }
  1597.     d2 = ~colors_for_drawing.acolors[0];
  1598.     while (pix < stoppos) {
  1599.     buf[pix] = d2;
  1600.     buf[pix+offset] = d2;
  1601.     pix++;
  1602.     }
  1603. }
  1604.  
  1605. static void inline fill_line_8(char *buf, int start, int stop)
  1606. {
  1607.     uae_u8 *b = (uae_u8 *)buf;
  1608.     int i;
  1609.     xcolnr col = ~colors_for_drawing.acolors[0];
  1610.     for (i = start; i < stop; i++)
  1611.         b[i] = col;
  1612. }
  1613. #else // !__mac__
  1614. LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0)
  1615. LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1)
  1616. FILL_LINE(fill_line_8, uae_u8)
  1617. #endif
  1618.  
  1619. LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0)
  1620. LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0)
  1621. LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1)
  1622. LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1)
  1623.  
  1624. FILL_LINE(fill_line_16, uae_u16)
  1625. FILL_LINE(fill_line_32, uae_u32)
  1626.  
  1627. static __inline__ void fill_line_full (void)
  1628. {
  1629.     switch (gfxvidinfo.pixbytes) {
  1630.      case 1: fill_line_8(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); break;
  1631.      case 2: fill_line_16(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); break;
  1632.      case 4: fill_line_32(xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.maxlinetoscr); break;
  1633.     }
  1634. }
  1635.  
  1636. #define fill_line fill_line_full
  1637.  
  1638. #define pfield_linetoscr_full8 pfield_linetoscr_8
  1639. #define pfield_linetoscr_full16 pfield_linetoscr_16
  1640. #define pfield_linetoscr_full32 pfield_linetoscr_32
  1641.  
  1642. #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
  1643. #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
  1644. #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
  1645.  
  1646. #if 1 && defined(X86_ASSEMBLY)
  1647. /* This version of fill_line is probably a win on all machines, but for
  1648.  * now I'm cautious */
  1649. #undef fill_line
  1650. static __inline__ void fill_line (void)
  1651. {
  1652.     int shift;
  1653.     int nints, nrem;
  1654.     int *start;
  1655.     xcolnr val;
  1656.  
  1657.     shift = 0;
  1658.     if (gfxvidinfo.pixbytes == 2)
  1659.     shift = 1;
  1660.     if (gfxvidinfo.pixbytes == 4)
  1661.     shift = 2;
  1662.  
  1663.     nints = gfxvidinfo.maxlinetoscr >> (2-shift);
  1664.     nrem = nints & 7;
  1665.     nints &= ~7;
  1666.     start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
  1667.     val = colors_for_drawing.acolors[0];
  1668.     for (; nints > 0; nints -= 8, start+=8) {
  1669.     *start = val;
  1670.     *(start+1) = val;
  1671.     *(start+2) = val;
  1672.     *(start+3) = val;
  1673.     *(start+4) = val;
  1674.     *(start+5) = val;
  1675.     *(start+6) = val;
  1676.     *(start+7) = val;
  1677.     }
  1678.     
  1679.     switch (nrem) {
  1680.      case 7:
  1681.     *start++ = val;
  1682.      case 6:
  1683.     *start++ = val;
  1684.      case 5:
  1685.     *start++ = val;
  1686.      case 4:
  1687.     *start++ = val;
  1688.      case 3:
  1689.     *start++ = val;
  1690.      case 2:
  1691.     *start++ = val;
  1692.      case 1:
  1693.     *start = val;
  1694.     }
  1695. }
  1696.  
  1697. #undef pfield_linetoscr_full8
  1698. /* The types are lies, of course. */
  1699. extern void pfield_linetoscr_normal_asm8(void) __asm__("pfield_linetoscr_normal_asm8");
  1700. extern void pfield_linetoscr_ehb_asm8(void) __asm__("pfield_linetoscr_ehb_asm8");
  1701. extern void pfield_linetoscr_ham6_asm8(void) __asm__("pfield_linetoscr_ham6_asm8");
  1702. extern void pfield_linetoscr_dualpf_asm8(void) __asm__("pfield_linetoscr_dualpf_asm8");
  1703. extern void pfield_linetoscr_hdouble_asm8(void) __asm__("pfield_linetoscr_hdouble_asm8");
  1704. extern void pfield_linetoscr_hdouble_dpf_asm8(void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
  1705. extern void pfield_linetoscr_hdouble_ehb_asm8(void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
  1706. extern void pfield_linetoscr_asm8(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
  1707.  
  1708. static void pfield_linetoscr_full8(int pix, int lframe_end, int diw_end, int stoppos)
  1709. {
  1710.     int lframe_end_1, diw_end_1;
  1711.  
  1712.     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
  1713.     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
  1714.  
  1715.     if (bplham && bplplanecnt == 6) {
  1716.     pfield_linetoscr_asm8(pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1717.     } else if (bpldualpf) {
  1718. #ifdef LORES_HACK
  1719.     if (currprefs.gfx_lores == 2)
  1720.         pfield_linetoscr_asm8(pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
  1721.                    bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1722.     else
  1723. #endif
  1724.         pfield_linetoscr_asm8(pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
  1725.                   bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1726.     } else if (bplehb) {
  1727. #ifdef LORES_HACK
  1728.     if (currprefs.gfx_lores == 2)
  1729.         pfield_linetoscr_asm8(pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1730.     else
  1731. #endif
  1732.         pfield_linetoscr_asm8(pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1733.     } else {
  1734. #ifdef LORES_HACK
  1735.     if (currprefs.gfx_lores == 2)
  1736.         pfield_linetoscr_asm8(pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1737.     else
  1738. #endif
  1739.         pfield_linetoscr_asm8(pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
  1740.     }
  1741.     
  1742.     /* The assembly functions work on aligned data, so we may have to do some
  1743.      * additional work at the edges. */
  1744.     if (lframe_end != lframe_end_1) {
  1745.     int i, c = colors_for_drawing.acolors[0];
  1746.     for (i = lframe_end_1; i < lframe_end; i++)
  1747.         xlinebuffer[i] = c;
  1748.     }
  1749.     if (diw_end != diw_end_1) {
  1750.     int i, c = colors_for_drawing.acolors[0];
  1751.     for (i = diw_end; i < diw_end_1; i++)
  1752.         xlinebuffer[i] = c;
  1753.     }
  1754. }
  1755.  
  1756. #undef pfield_linetoscr_full16
  1757. extern void pfield_linetoscr_normal_asm16(void) __asm__("pfield_linetoscr_normal_asm16");
  1758. extern void pfield_linetoscr_ehb_asm16(void) __asm__("pfield_linetoscr_ehb_asm16");
  1759. extern void pfield_linetoscr_ham6_asm16(void) __asm__("pfield_linetoscr_ham6_asm16");
  1760. extern void pfield_linetoscr_dualpf_asm16(void) __asm__("pfield_linetoscr_dualpf_asm16");
  1761. extern void pfield_linetoscr_hdouble_asm16(void) __asm__("pfield_linetoscr_hdouble_asm16");
  1762. extern void pfield_linetoscr_hdouble_dpf_asm16(void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
  1763. extern void pfield_linetoscr_hdouble_ehb_asm16(void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
  1764. extern void pfield_linetoscr_asm16(void (*)(void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
  1765.  
  1766. static void pfield_linetoscr_full16(int pix, int lframe_end, int diw_end, int stoppos)
  1767. {
  1768.     int lframe_end_1, diw_end_1;
  1769.  
  1770.     lframe_end_1 = pix + ((lframe_end - pix) & ~3);
  1771.     diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
  1772.  
  1773.     if (bplham && bplplanecnt == 6) {
  1774.     pfield_linetoscr_asm16(pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1775.     } else if (bpldualpf) {
  1776. #ifdef LORES_HACK
  1777.     if (currprefs.gfx_lores == 2)
  1778.         pfield_linetoscr_asm16(pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
  1779.                    bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1780.     else
  1781. #endif
  1782.         pfield_linetoscr_asm16(pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
  1783.                    bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
  1784.     } else if (bplehb) {
  1785. #ifdef LORES_HACK
  1786.     if (currprefs.gfx_lores == 2)
  1787.         pfield_linetoscr_asm16(pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1788.     else
  1789. #endif
  1790.         pfield_linetoscr_asm16(pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1791.     } else {
  1792. #ifdef LORES_HACK
  1793.     if (currprefs.gfx_lores == 2)
  1794.         pfield_linetoscr_asm16(pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1795.     else
  1796. #endif
  1797.         pfield_linetoscr_asm16(pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
  1798.     }
  1799.  
  1800.     /* The assembly functions work on aligned data, so we may have to do some
  1801.      * additional work at the edges. */
  1802.     if (lframe_end != lframe_end_1) {
  1803.     int i, c = colors_for_drawing.acolors[0];
  1804.     for (i = lframe_end_1; i < lframe_end; i++)
  1805.         ((uae_u16 *)xlinebuffer)[i] = c;
  1806.     }
  1807.     if (diw_end != diw_end_1) {
  1808.     int i, c = colors_for_drawing.acolors[0];
  1809.     for (i = diw_end; i < diw_end_1; i++)
  1810.         ((uae_u16 *)xlinebuffer)[i] = c;
  1811.     }
  1812. }
  1813.  
  1814. #ifndef NO_DOUBLING_LINETOSCR
  1815. #define NO_DOUBLING_LINETOSCR
  1816. #endif
  1817.  
  1818. #endif
  1819.  
  1820. #ifdef NO_DOUBLING_LINETOSCR
  1821. #undef pfield_linetoscr_full8_double
  1822. #undef pfield_linetoscr_full16_double
  1823. static void pfield_linetoscr_full8_double(int start, int lframe_end, int diw_end, int stop)
  1824. {
  1825.     char *oldxlb = (char *)xlinebuffer;
  1826.     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
  1827.     xlinebuffer = oldxlb + linetoscr_double_offset;
  1828.     pfield_linetoscr_full8(start, lframe_end, diw_end, stop);
  1829. }
  1830. static void pfield_linetoscr_full16_double(int start, int lframe_end, int diw_end, int stop)
  1831. {
  1832.     char *oldxlb = (char *)xlinebuffer;
  1833.     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
  1834.     xlinebuffer = oldxlb + linetoscr_double_offset;
  1835.     pfield_linetoscr_full16(start, lframe_end, diw_end, stop);
  1836. }
  1837. #endif
  1838.  
  1839. static int linetoscr_diw_end, linetoscr_diw_start;
  1840.  
  1841. static void pfield_init_linetoscr (void)
  1842. {
  1843.     int ddf_left, ddf_right;
  1844.     int mindelay = bpldelay1, maxdelay = bpldelay2;
  1845.     if (bpldelay1 > bpldelay2)
  1846.     maxdelay = bpldelay1, mindelay = bpldelay2;
  1847.  
  1848.     linetoscr_diw_start = dp_for_drawing->diwfirstword;
  1849.     linetoscr_diw_end = dp_for_drawing->diwlastword;
  1850.  
  1851.     /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
  1852.      * so that centering works better, but I'm afraid that might cost too many
  1853.      * cycles. Plus it's dangerous, see the code below that handles the case 
  1854.      * with sprites. */
  1855.     if (dip_for_drawing->nr_sprites == 0) {
  1856.     int hiresadjust = bplhires ? 4 : 8;
  1857.     ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1858.     ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1859.     
  1860.     if (linetoscr_diw_start < ddf_left)
  1861.         linetoscr_diw_start = ddf_left;
  1862.     if (linetoscr_diw_end > ddf_right)
  1863.         linetoscr_diw_end = ddf_right;
  1864.  
  1865.     if (mindelay != maxdelay) {
  1866.         /* Raahh...
  1867.          * We just clear the maximum amount of space that may need to be
  1868.          * cleared. We could do this exactly, but it would come out slower
  1869.          * because of the overhead. */
  1870.         int strt = ddf_left;
  1871.         if (currprefs.gfx_lores == 2) {
  1872.         fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
  1873.         fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
  1874.         } else if (currprefs.gfx_lores) {
  1875.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
  1876.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
  1877.         } else {
  1878.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
  1879.         fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
  1880.         }
  1881.     }
  1882.     } else {
  1883.     int hiresadjust = bplhires ? 4 : 8;
  1884.     /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
  1885.      * Since we have to do a memset anyway (because there may be sprites),
  1886.      * we might as well clear all at once. */
  1887.     ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1888.     ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
  1889.     if (linetoscr_diw_start < ddf_left) {
  1890.         int strt = linetoscr_diw_start;
  1891.         int stop = ddf_left;
  1892. #ifdef LORES_HACK
  1893.         if (currprefs.gfx_lores == 2)
  1894.         strt >>= 1, stop >>= 1;
  1895. #endif
  1896.         if (strt < stop)
  1897.         fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
  1898.     }
  1899.  
  1900.     if (linetoscr_diw_end > ddf_right) {
  1901.         int strt = ddf_right;
  1902.         int stop = linetoscr_diw_end;
  1903. #ifdef LORES_HACK
  1904.         if (currprefs.gfx_lores == 2)
  1905.         strt >>= 1, stop >>= 1;
  1906. #endif
  1907.         if (strt < stop)
  1908.         fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
  1909.     }
  1910.     }
  1911.     /* Perverse cases happen. */
  1912.     if (linetoscr_diw_end < linetoscr_diw_start)
  1913.     linetoscr_diw_end = linetoscr_diw_start;
  1914. }
  1915.  
  1916. static void pfield_do_linetoscr(int start, int stop)
  1917. {
  1918.     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
  1919.  
  1920.     if (stop > linetoscr_right_x)
  1921.     stop = linetoscr_right_x;
  1922.     if (start < linetoscr_x_adjust)
  1923.     start = linetoscr_x_adjust;
  1924.     
  1925.     if (lframe_end < start)
  1926.     lframe_end = start;
  1927.     if (diw_end > stop)
  1928.     diw_end = stop;
  1929.  
  1930.     if (start >= stop)
  1931.     return;
  1932.  
  1933. #if AGA_CHIPSET == 0
  1934.     if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
  1935.     switch (gfxvidinfo.pixbytes) {
  1936.      case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
  1937.      case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
  1938.      case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
  1939.     }
  1940.     } else {
  1941.     switch (gfxvidinfo.pixbytes) {
  1942.      case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
  1943.      case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
  1944.      case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
  1945.     }
  1946.     }
  1947. #else
  1948.     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
  1949. #endif
  1950. }
  1951.  
  1952. static void pfield_do_fill_line(int start, int stop)
  1953. {
  1954.     if (stop > linetoscr_right_x)
  1955.     stop = linetoscr_right_x;
  1956.     if (start < linetoscr_x_adjust)
  1957.     start = linetoscr_x_adjust;
  1958.  
  1959.     if (start >= stop)
  1960.     return;
  1961.  
  1962.     switch (gfxvidinfo.pixbytes) {
  1963.      case 1: fill_line_8 (xlinebuffer, start, stop); break;
  1964.      case 2: fill_line_16 (xlinebuffer, start, stop); break;
  1965.      case 4: fill_line_32 (xlinebuffer, start, stop); break;
  1966.     }
  1967. }
  1968.  
  1969. static void pfield_do_linetoscr_full(int double_line)
  1970. {
  1971.     int start = linetoscr_x_adjust, stop = start + gfxvidinfo.maxlinetoscr;
  1972.     int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
  1973.     if (lframe_end < start)
  1974.     lframe_end = start;
  1975.     if (diw_end > stop)
  1976.     diw_end = stop;
  1977.  
  1978. #if AGA_CHIPSET == 0
  1979.     if (double_line) {
  1980.     switch (gfxvidinfo.pixbytes) {
  1981.      case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
  1982.      case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
  1983.      case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
  1984.     }
  1985.     } else 
  1986.     switch (gfxvidinfo.pixbytes) {
  1987.      case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
  1988.      case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
  1989.      case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
  1990.     }
  1991. #else
  1992.     pfield_linetoscr_aga(start, lframe_end, diw_end, stop);
  1993. #endif
  1994. }
  1995.  
  1996.  /* 
  1997.   * register functions
  1998.   */
  1999.  
  2000. uae_u16 DMACONR(void)
  2001. {
  2002.     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
  2003.         | (blt_info.blitzero ? 0x2000 : 0));
  2004. }
  2005. static uae_u16 INTENAR(void) { return intena; }
  2006. uae_u16 INTREQR(void)
  2007. {
  2008.     return intreq | (currprefs.use_serial ? 0x0001 : 0);
  2009. }
  2010. static uae_u16 ADKCONR(void) { return adkcon; }
  2011. static uae_u16 VPOSR(void) 
  2012. {
  2013. #if AGA_CHIPSET == 1
  2014.     return (vpos >> 8) | lof | 0x2300;
  2015. #elif defined (ECS_AGNUS)
  2016.     return (vpos >> 8) | lof | 0x2000;
  2017. #else
  2018.     return (vpos >> 8) | lof;
  2019. #endif
  2020. }
  2021. static void  VPOSW(uae_u16 v)
  2022. {
  2023.     if (lof != (v & 0x8000))
  2024.     lof_changed = 1;
  2025.     lof = v & 0x8000;
  2026. }
  2027. static uae_u16 VHPOSR(void) { return (vpos << 8) | current_hpos(); } 
  2028.  
  2029. static void  COP1LCH(uae_u16 v) { cop1lc= (cop1lc & 0xffff) | ((uae_u32)v << 16); }
  2030. static void  COP1LCL(uae_u16 v) { cop1lc= (cop1lc & ~0xffff) | v; }
  2031. static void  COP2LCH(uae_u16 v) { cop2lc= (cop2lc & 0xffff) | ((uae_u32)v << 16); }
  2032. static void  COP2LCL(uae_u16 v) { cop2lc= (cop2lc & ~0xffff) | v; }
  2033.  
  2034. static void  COPJMP1(uae_u16 a)
  2035. {
  2036.     coplc = cop1lc; copstate = COP_read; 
  2037.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  2038.     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
  2039.     copper_active = 1;
  2040.     copper_waiting_for_blitter = 0;
  2041. }
  2042. static void  COPJMP2(uae_u16 a)
  2043. {
  2044.     coplc = cop2lc; copstate = COP_read; 
  2045.     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
  2046.     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
  2047.     copper_active = 1;
  2048.     copper_waiting_for_blitter = 0;
  2049. }
  2050. static void  COPCON(uae_u16 a) { copcon = a; }
  2051. static void  DMACON(uae_u16 v) 
  2052. {
  2053.     int i, need_resched = 0;
  2054.  
  2055.     uae_u16 oldcon = dmacon;
  2056.     
  2057.     decide_line();
  2058.     setclr(&dmacon,v); dmacon &= 0x1FFF;
  2059.     post_decide_line ();
  2060.     
  2061.     /* FIXME? Maybe we need to think a bit more about the master DMA enable 
  2062.      * bit in these cases. */
  2063.     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { 
  2064.     COPJMP1(0);
  2065.     }
  2066.     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
  2067.     static int count = 0;
  2068.     if (!count) {
  2069.         count = 1;
  2070.         write_log ("warning: program is doing blitpri hacks.\n");
  2071.     }
  2072.     regs.spcflags |= SPCFLAG_BLTNASTY;
  2073.     }
  2074. #ifndef DONT_WANT_SOUND
  2075.     for (i = 0; i < 4; i++) {
  2076.     struct audio_channel_data *cdp = audio_channel + i;
  2077.     
  2078.     cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i));
  2079.     if (cdp->dmaen) {
  2080.         if (cdp->state == 0) {
  2081.         cdp->state = 1;
  2082.         cdp->pt = cdp->lc;
  2083.         cdp->wper = cdp->per;
  2084.         cdp->wlen = cdp->len;
  2085.         cdp->data_written = 2;
  2086.         eventtab[ev_aud0 + i].oldcycles = eventtab[ev_hsync].oldcycles;
  2087.         eventtab[ev_aud0 + i].evtime = eventtab[ev_hsync].evtime;
  2088.         eventtab[ev_aud0 + i].active = 1;
  2089.         need_resched = 1; /* not _really_ necessary here, but... */
  2090.         }
  2091.     } else {
  2092.         if (cdp->state == 1 || cdp->state == 5) {
  2093.         cdp->state = 0;
  2094.         cdp->current_sample = 0;
  2095.         eventtab[ev_aud0 + i].active = 0;
  2096.         need_resched = 1;
  2097.         }
  2098.     }
  2099.     }
  2100. #endif
  2101.     calculate_copper_cycle_time ();
  2102.     if (copper_active && !eventtab[ev_copper].active) {
  2103.     eventtab[ev_copper].active = 1;
  2104.     eventtab[ev_copper].oldcycles = cycles;
  2105.     eventtab[ev_copper].evtime = 1 + cycles;
  2106.     need_resched = 1;
  2107.     }
  2108.     if (need_resched)
  2109.     events_schedule();
  2110. }
  2111.  
  2112. /*static int trace_intena = 0;*/
  2113.  
  2114. static void  INTENA(uae_u16 v) 
  2115. {
  2116. /*    if (trace_intena)
  2117.     fprintf(stderr, "INTENA: %04x\n", v);*/
  2118.     setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; 
  2119. }
  2120. void  INTREQ(uae_u16 v)
  2121. {
  2122.     setclr(&intreq,v);
  2123.     regs.spcflags |= SPCFLAG_INT;
  2124.     if ((v&0x8800)==0x0800) serdat&=0xbfff;
  2125. }
  2126.  
  2127. static void  ADKCON(uae_u16 v) { setclr(&adkcon,v); }
  2128.  
  2129. static void  BPLPTH(uae_u16 v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); }
  2130. static void  BPLPTL(uae_u16 v, int num) { decide_line (); decide_plane(); do_modulos(); bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); }
  2131.  
  2132. static void  BPLCON0(uae_u16 v)
  2133. {
  2134. #if AGA_CHIPSET == 0
  2135.     v &= 0xFF0E;
  2136.     /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect")
  2137.      * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */
  2138.     if ((v & 0xF000) > 0xC000)
  2139.     v &= 0xFFF;
  2140.     /* Don't want 7 lores planes either. */
  2141.     if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000)
  2142.     v &= 0xEFFF;
  2143. #endif
  2144.     if (bplcon0 == v)
  2145.     return;
  2146.     decide_line ();
  2147.     bplcon0 = v;
  2148.     nr_planes_from_bplcon0 = (bplcon0 >> 12) & 7;
  2149.     corrected_nr_planes_from_bplcon0 = ((bplcon0 >> 12) & 7) << (bplcon0 & 0x8000 ? 1 : 0);
  2150.     post_decide_line ();
  2151.     calculate_copper_cycle_time ();
  2152. #if 0
  2153.     calcdiw(); /* This should go away. */
  2154. #endif
  2155. }
  2156. static void  BPLCON1(uae_u16 v) 
  2157. {
  2158.     if (bplcon1 == v)
  2159.     return;
  2160.     decide_diw ();
  2161.     bplcon1 = v;
  2162.     decide_delay ();
  2163. }
  2164. static void  BPLCON2(uae_u16 v) 
  2165. {
  2166.     if (bplcon2 != v)
  2167.     decide_line ();
  2168.     bplcon2 = v;
  2169. }
  2170. static void  BPLCON3(uae_u16 v) 
  2171. {
  2172.     if (bplcon3 != v)
  2173.     decide_line ();
  2174.     bplcon3 = v; 
  2175. }
  2176. static void  BPLCON4(uae_u16 v) 
  2177. {
  2178.     if (bplcon4 != v)
  2179.     decide_line ();
  2180.     bplcon4 = v; 
  2181. }
  2182.  
  2183. static void  BPL1MOD(uae_u16 v)
  2184. {
  2185.     v &= ~1;
  2186.     if ((uae_s16)bpl1mod == (uae_s16)v)
  2187.     return;
  2188.     bpl1mod = v;
  2189.     decide_modulos ();
  2190. }
  2191.  
  2192. static void  BPL2MOD(uae_u16 v)
  2193.     v &= ~1;
  2194.     if ((uae_s16)bpl2mod == (uae_s16)v)
  2195.     return;
  2196.     bpl2mod = v;
  2197.     decide_modulos();
  2198. }
  2199.  
  2200. /* We could do as well without those... */
  2201. static void  BPL1DAT(uae_u16 v) { bpl1dat = v; }
  2202. static void  BPL2DAT(uae_u16 v) { bpl2dat = v; }
  2203. static void  BPL3DAT(uae_u16 v) { bpl3dat = v; }
  2204. static void  BPL4DAT(uae_u16 v) { bpl4dat = v; }
  2205. static void  BPL5DAT(uae_u16 v) { bpl5dat = v; }
  2206. static void  BPL6DAT(uae_u16 v) { bpl6dat = v; }
  2207.  
  2208. static void  DIWSTRT(uae_u16 v) 
  2209. {
  2210.     if (diwstrt == v)
  2211.     return;
  2212.     decide_line ();
  2213.     diwstrt = v; 
  2214.     calcdiw();
  2215. }
  2216. static void  DIWSTOP(uae_u16 v)
  2217. {
  2218.     if (diwstop == v)
  2219.     return;
  2220.     diwstop = v; 
  2221.     calcdiw();
  2222. }
  2223. static void  DDFSTRT(uae_u16 v)
  2224.     v &= 0xFF;
  2225.     if (ddfstrt == v)
  2226.     return;
  2227.     decide_line ();
  2228.     ddfstrt = v; 
  2229.     calcdiw();
  2230. }
  2231. static void  DDFSTOP(uae_u16 v) 
  2232.     v &= 0xFF;
  2233.     if (ddfstop == v)
  2234.     return;
  2235.     decide_line ();
  2236.     ddfstop = v;
  2237.     calcdiw();
  2238. }
  2239.  
  2240. static void  BLTADAT(uae_u16 v) 
  2241. {
  2242.     maybe_blit();
  2243.  
  2244.     blt_info.bltadat = v;
  2245. }
  2246. /*
  2247.  * "Loading data shifts it immediately" says the HRM. Well, that may
  2248.  * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
  2249.  * loaded for every word so that AFWM and ALWM can be applied.
  2250.  */
  2251. static void  BLTBDAT(uae_u16 v)
  2252. {
  2253.     maybe_blit(); 
  2254.  
  2255.     if (bltcon1 & 2)
  2256.     blt_info.bltbhold = v << (bltcon1 >> 12);
  2257.     else
  2258.     blt_info.bltbhold = v >> (bltcon1 >> 12);
  2259.     blt_info.bltbdat = v;
  2260. }
  2261. static void BLTCDAT(uae_u16 v) { maybe_blit(); blt_info.bltcdat = v; }
  2262.  
  2263. static void BLTAMOD(uae_u16 v) { maybe_blit(); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
  2264. static void BLTBMOD(uae_u16 v) { maybe_blit(); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
  2265. static void BLTCMOD(uae_u16 v) { maybe_blit(); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
  2266. static void BLTDMOD(uae_u16 v) { maybe_blit(); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
  2267.  
  2268. static void BLTCON0(uae_u16 v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; }
  2269. /* The next category is "Most useless hardware register". 
  2270.  * And the winner is... */
  2271. static void BLTCON0L(uae_u16 v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); }
  2272. static void BLTCON1(uae_u16 v) { maybe_blit(); bltcon1 = v; }
  2273.  
  2274. static void BLTAFWM(uae_u16 v) { maybe_blit(); blt_info.bltafwm = v; }
  2275. static void BLTALWM(uae_u16 v) { maybe_blit(); blt_info.bltalwm = v; }
  2276.  
  2277. static void BLTAPTH(uae_u16 v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((uae_u32)v << 16); }
  2278. static void BLTAPTL(uae_u16 v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); }
  2279. static void BLTBPTH(uae_u16 v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((uae_u32)v << 16); }
  2280. static void BLTBPTL(uae_u16 v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); }
  2281. static void BLTCPTH(uae_u16 v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((uae_u32)v << 16); }
  2282. static void BLTCPTL(uae_u16 v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); }
  2283. static void BLTDPTH(uae_u16 v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((uae_u32)v << 16); }
  2284. static void BLTDPTL(uae_u16 v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); }
  2285. static void BLTSIZE(uae_u16 v) 
  2286. {
  2287.     bltsize = v;
  2288.     
  2289.     maybe_blit(); 
  2290.  
  2291.     blt_info.vblitsize = bltsize >> 6;
  2292.     blt_info.hblitsize = bltsize & 0x3F;
  2293.     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
  2294.     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
  2295.     
  2296.     bltstate = BLT_init; 
  2297.     do_blitter();
  2298. }
  2299. static void BLTSIZV(uae_u16 v) 
  2300. {
  2301.     maybe_blit(); 
  2302.     oldvblts = v & 0x7FFF;
  2303. }
  2304. static void BLTSIZH(uae_u16 v)
  2305. {
  2306.     maybe_blit();
  2307.     blt_info.hblitsize = v & 0x7FF;
  2308.     blt_info.vblitsize = oldvblts;
  2309.     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
  2310.     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
  2311.     bltstate = BLT_init;
  2312.     do_blitter();
  2313. }
  2314. static void SPRxCTL_1(uae_u16 v, int num)
  2315. {
  2316.     int sprxp;
  2317.     sprctl[num] = v;
  2318.     nr_armed -= sprarmed[num];
  2319.     sprarmed[num] = 0;
  2320.     if (sprpos[num] == 0 && v == 0) {
  2321.     sprst[num] = SPR_stop;
  2322.     spron[num] = 0;
  2323.     } else
  2324.     sprst[num] = SPR_waiting_start;
  2325.  
  2326.     sprxp = ((sprpos[num] & 0xFF) * 2) + (v & 1) - DISPLAY_LEFT_SHIFT;
  2327.     if (!currprefs.gfx_lores)
  2328.     sprxp *= 2;
  2329.     sprxpos[num] = sprxp;
  2330.     sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
  2331.     sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
  2332. }
  2333. static void SPRxPOS_1(uae_u16 v, int num) 
  2334. {
  2335.     int sprxp;
  2336.     sprpos[num] = v;
  2337.     sprxp = ((v & 0xFF) * 2) + (sprctl[num] & 1) - DISPLAY_LEFT_SHIFT;
  2338.     if (!currprefs.gfx_lores)
  2339.     sprxp *= 2;
  2340.     sprxpos[num] = sprxp;
  2341.     sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
  2342. }
  2343. static void SPRxDATA_1(uae_u16 v, int num)
  2344. {
  2345.     sprdata[num] = v;
  2346.     nr_armed += 1 - sprarmed[num];
  2347.     sprarmed[num] = 1;
  2348. }
  2349. static void SPRxDATB_1(uae_u16 v, int num)
  2350. {
  2351.     sprdatb[num] = v;
  2352. }
  2353. static void SPRxDATA(uae_u16 v, int num) { decide_sprites (); SPRxDATA_1 (v, num); }
  2354. static void SPRxDATB(uae_u16 v, int num) { decide_sprites (); SPRxDATB_1 (v, num); }
  2355. static void SPRxCTL(uae_u16 v, int num) { decide_sprites (); SPRxCTL_1 (v, num); }
  2356. static void SPRxPOS(uae_u16 v, int num) { decide_sprites (); SPRxPOS_1 (v, num); }
  2357. static void SPRxPTH(uae_u16 v, int num)
  2358. {
  2359.     decide_line ();
  2360.     sprpt[num] &= 0xffff; 
  2361.     sprpt[num] |= (uae_u32)v << 16;
  2362.  
  2363.     if (sprst[num] == SPR_stop)
  2364.     sprst[num] = SPR_restart;
  2365.     spron[num] = 1;
  2366. }
  2367. static void SPRxPTL(uae_u16 v, int num)
  2368. {
  2369.     decide_line ();
  2370.     sprpt[num] &= ~0xffff; 
  2371.     sprpt[num] |= v;
  2372.  
  2373.     if (sprst[num] == SPR_stop)
  2374.     sprst[num] = SPR_restart;
  2375.     spron[num] = 1;
  2376. }
  2377. static void CLXCON(uae_u16 v)
  2378. {
  2379.     clxcon = v;
  2380.     clx_sprmask = (((v >> 15) << 7) | ((v >> 14) << 5) | ((v >> 13) << 3) | ((v >> 12) << 1) | 0x55);
  2381. }
  2382. static uae_u16 CLXDAT(void)
  2383. {
  2384.     uae_u16 v = clxdat;
  2385.     clxdat = 0;
  2386.     return v;
  2387. }
  2388. static void COLOR(uae_u16 v, int num)
  2389. {
  2390.     int r,g,b;
  2391.     int cr,cg,cb;
  2392.     int colreg;
  2393.     
  2394.     v &= 0xFFF;
  2395. #if AGA_CHIPSET == 1
  2396.     {
  2397.     /* XXX Broken */
  2398.     uae_u32 cval;
  2399.     colreg = ((bplcon3 >> 13) & 7) * 32 + num;
  2400.     r = (v & 0xF00) >> 8;
  2401.     g = (v & 0xF0) >> 4;
  2402.     b = (v & 0xF) >> 0;
  2403.     cr = color_regs[colreg] >> 16;
  2404.     cg = (color_regs[colreg] >> 8) & 0xFF;
  2405.     cb = color_regs[colreg] & 0xFF;
  2406.  
  2407.     if (bplcon3 & 0x200) {
  2408.         cr &= 0xF0; cr |= r;
  2409.         cg &= 0xF0; cg |= g;
  2410.         cb &= 0xF0; cb |= b;
  2411.     } else {
  2412.         cr = r + (r << 4);
  2413.         cg = g + (g << 4);
  2414.         cb = b + (b << 4);
  2415.     }
  2416.     cval = (cr << 16) | (cg << 8) | cb;
  2417.     if (cval == color_regs[colreg])
  2418.         return;
  2419.     color_regs[colreg] = cval;
  2420.     pfield_may_need_update(1);
  2421.     }
  2422. #else 
  2423.     {
  2424.     if (current_colors.color_regs[num] == v)
  2425.         return;
  2426.     /* Call this with the old table still intact. */
  2427.     record_color_change (num, v);
  2428.     remembered_color_entry = -1;
  2429.     current_colors.color_regs[num] = v;
  2430.     current_colors.acolors[num] = xcolors[v];
  2431.     }
  2432. #endif
  2433. }
  2434.  
  2435. static void  DSKSYNC(uae_u16 v) { dsksync = v; }
  2436. static void  DSKDAT(uae_u16 v) { write_log ("DSKDAT written. Not good.\n"); }
  2437. static void  DSKPTH(uae_u16 v) { dskpt = (dskpt & 0xffff) | ((uae_u32)v << 16); }
  2438. static void  DSKPTL(uae_u16 v) { dskpt = (dskpt & ~0xffff) | (v); }
  2439.  
  2440. static void  DSKLEN(uae_u16 v) 
  2441. {
  2442.     if (v & 0x8000) {
  2443.     dskdmaen = dskdmaen == 1 ? 2 : 1;
  2444.     } else { 
  2445.     dskdmaen = 0;
  2446.     if (eventtab[ev_diskblk].active)
  2447.         write_log ("warning: Disk DMA aborted!\n");
  2448.     eventtab[ev_diskblk].active = 0;
  2449.     events_schedule();
  2450.     
  2451.     }
  2452.     dsklen = dsklength = v; dsklength &= 0x3fff;
  2453.     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
  2454.     sprintf (warning_buffer, "Non-standard sync: %04x len: %x\n", dsksync, dsklength);
  2455.     write_log (warning_buffer);
  2456.     }
  2457.     if (dskdmaen > 1) {
  2458.     if (dsklen & 0x4000) {
  2459.         eventtab[ev_diskblk].active = 1;
  2460.         eventtab[ev_diskblk].oldcycles = cycles;
  2461.         eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */
  2462.         events_schedule();
  2463.     } else {
  2464.         int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400);
  2465.         if (result) {
  2466.         eventtab[ev_diskblk].active = 1;
  2467.         eventtab[ev_diskblk].oldcycles = cycles;
  2468.         eventtab[ev_diskblk].evtime = result + cycles;
  2469.         events_schedule();
  2470.         }
  2471.     }
  2472.     }
  2473. }
  2474.  
  2475. static uae_u16 DSKBYTR(void)
  2476. {
  2477.     uae_u16 v = (dsklen >> 1) & 0x6000;
  2478.     uae_u16 mfm, byte;
  2479.     if (DISK_GetData(&mfm, &byte))
  2480.     v |= 0x8000;
  2481.     v |= byte;
  2482.     if (dsksync == mfm) v |= 0x1000;
  2483.     return v;
  2484. }
  2485.  
  2486. static uae_u16 DSKDATR(void) 
  2487. {
  2488.     uae_u16 mfm, byte;
  2489.     DISK_GetData(&mfm, &byte);
  2490.     return mfm; 
  2491. }
  2492. static uae_u16 POTGOR(void)
  2493. {
  2494.     uae_u16 v = 0xFF00;
  2495.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2496.     if (buttonstate[2])
  2497.         v &= 0xFBFF;
  2498.  
  2499.     if (buttonstate[1])
  2500.         v &= 0xFEFF;
  2501.     }
  2502.     else if (JSEM_ISJOY0(0, currprefs.fake_joystick) || JSEM_ISJOY1(0, currprefs.fake_joystick)) {
  2503.         if (joy0button & 2) v &= 0xfbff;
  2504.         if (joy0button & 4) v &= 0xfeff;
  2505.     }
  2506.  
  2507.     if (JSEM_ISJOY0(1, currprefs.fake_joystick) || JSEM_ISJOY1(1, currprefs.fake_joystick)) {
  2508.         if (joy1button & 2) v &= 0xbfff;
  2509.         if (joy1button & 4) v &= 0xefff;
  2510.     }
  2511.         
  2512.     return v;
  2513. }
  2514. static uae_u16 POT0DAT(void)
  2515. {
  2516.     static uae_u16 cnt = 0;
  2517.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2518.     if (buttonstate[2])
  2519.         cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
  2520.     if (buttonstate[1])
  2521.         cnt += 0x100;
  2522.     }
  2523.  
  2524.     return cnt;
  2525. }
  2526. static uae_u16 JOY0DAT(void)
  2527. {
  2528.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2529.     return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
  2530.     }
  2531.     return joy0dir;
  2532. }
  2533. static uae_u16 JOY1DAT(void)
  2534. {
  2535.     if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) {
  2536.     return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8);
  2537.     }
  2538.     return joy1dir;
  2539. }
  2540. static void JOYTEST(uae_u16 v)
  2541. {
  2542.     if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) {
  2543.     mouse_x = v & 0xFC;
  2544.     mouse_y = (v >> 8) & 0xFC;
  2545.     }
  2546. }
  2547. static void AUDxLCH(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16); }
  2548. static void AUDxLCL(int nr, uae_u16 v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); }
  2549. static void AUDxPER(int nr, uae_u16 v)
  2550. {
  2551.     if (v <= 0) {
  2552. #if 0 /* v == 0 is rather common, and harmless, and the value isn't signed anyway */
  2553.     static int warned = 0;
  2554.     if (!warned)
  2555.         write_log ("Broken program accessing the sound hardware\n"), warned++;
  2556. #endif
  2557.     v = 65535;
  2558.     }
  2559.     if (v < maxhpos/2 && currprefs.produce_sound < 3)
  2560.     v = maxhpos/2;
  2561.  
  2562.     audio_channel[nr].per = v;
  2563. }
  2564.  
  2565. static void AUDxVOL(int nr, uae_u16 v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; }
  2566. static void AUDxLEN(int nr, uae_u16 v) { audio_channel[nr].len = v; }
  2567.  
  2568. /*
  2569.  * Here starts the copper code. It should be rewritten.
  2570.  */
  2571.  
  2572. #define COPPER_ALTERNATIVE 1
  2573. /*
  2574.  * Calculate the minimum number of cycles after which the
  2575.  * copper comparison becomes true. This is quite tricky. I hope it works.
  2576.  */
  2577. static int calc_copcomp_true(int currvpos, int currhpos)
  2578. {    
  2579.     uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2580.     uae_u16 hp = currhpos & (copi2 & 0xFE);
  2581.     uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
  2582.     uae_u16 hcmp = (copi1 & copi2 & 0xFE);
  2583.     int copper_time_hpos;
  2584.     int cycleadd = maxhpos - currhpos;
  2585.     int coptime = 0;
  2586.     int maxwait = 32767;
  2587.  
  2588. #if COPPER_ALTERNATIVE == 0
  2589.     /* This is a kludge... the problem is that there are programs that wait for
  2590.      * FFDDFFFE and then for a line in the second display half, and this doesn't
  2591.      * work without this. I _think_ the reason why it works on the Amiga is that
  2592.      * the last cycle in the line isn't available for the copper, but I'm not sure.
  2593.      * OTOH, I'm pretty convinced that the copper timings are correct otherwise, so
  2594.      * I added this rather than changing something else. */
  2595.     if (hcmp == 0xDC)
  2596.     hcmp += 2;
  2597. #endif
  2598.     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
  2599.         return 0;    
  2600.  
  2601.     try_again:
  2602.  
  2603.     while (vp < vcmp) {
  2604.     currvpos++;
  2605.     if (currvpos > maxvpos + 1)
  2606.         return -1;
  2607.     currhpos = 0;
  2608.     coptime += cycleadd;
  2609.     cycleadd = maxhpos;
  2610.     vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2611.     }
  2612.     if ((bplcon0 & 0xF000) == 0xC000) {
  2613.     if (coptime > 0)
  2614.         return coptime;
  2615.     maxwait = plfstrt - current_hpos();
  2616.     if (maxwait < 0)
  2617.         maxwait = 32767;
  2618.     }
  2619.     copper_time_hpos = currhpos;
  2620.     hp = copper_time_hpos & (copi2 & 0xFE);
  2621.     if (!(vp > vcmp)) {    
  2622.     while ((int)hp < ((int)hcmp)) {
  2623.         currhpos++;
  2624.         /* Copper DMA is turned off in Hires 4 bitplane mode */
  2625.         if (decided_nr_planes != 4 /* -1 if before plfstrt */
  2626.         || !decided_hires
  2627.         || current_hpos () >= (thisline_decision.plfstrt + thisline_decision.plflinelen))
  2628.         copper_time_hpos++;
  2629.         
  2630.         if (currhpos > maxhpos) {
  2631.         /* Now, what? There might be a good position on the
  2632.          * next line. But it can also be the FFFF FFFE
  2633.          * case.
  2634.          */
  2635.         currhpos = 0;
  2636.         currvpos++;
  2637.         vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2638.         goto try_again;
  2639.         }
  2640.         coptime++;
  2641.         if (coptime >= maxwait)
  2642.         return coptime;
  2643.         hp = copper_time_hpos & (copi2 & 0xFE);
  2644.     }
  2645.     }
  2646.     if (coptime == 0) /* waiting for the blitter */
  2647.         return 1;
  2648.  
  2649.     return coptime;
  2650. }
  2651.  
  2652. /*
  2653.  * Simple version of the above which only tries to get vpos correct.
  2654.  */
  2655. static int calc_copcomp_true_vpos(int currvpos, int currhpos)
  2656. {    
  2657.     uae_u16 vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2658.     uae_u16 hp = currhpos & (copi2 & 0xFE);
  2659.     uae_u16 vcmp = ((copi1 & (copi2 | 0x8000)) >> 8);
  2660.     uae_u16 hcmp = (copi1 & copi2 & 0xFE);
  2661.     int copper_time_hpos;
  2662.     int cycleadd = maxhpos - currhpos;
  2663.     int coptime = 0;
  2664. #if COPPER_ALTERNATIVE == 0
  2665.     /* see above */
  2666.     if (hcmp == 0xDC)
  2667.     hcmp += 2;
  2668. #endif
  2669.     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
  2670.         return 0;    
  2671.  
  2672.     while (vp < vcmp) {
  2673.     currvpos++;
  2674.     if (currvpos > maxvpos + 1)
  2675.         return -1;
  2676.     currhpos = 0;
  2677.     coptime += cycleadd;
  2678.     cycleadd = maxhpos;
  2679.     vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
  2680.     }
  2681.     return coptime;
  2682. }
  2683.  
  2684. static enum copper_states cop_cmds[4] = { COP_move, COP_wait, COP_move, COP_skip };
  2685.  
  2686. /* This function is not always correct, but it's the best we can do. */
  2687. static int copper_memory_cycles (int n)
  2688. {
  2689.     int current_cycle = current_hpos ();
  2690.     int n_needed = 0;
  2691.     int planes = corrected_nr_planes_from_bplcon0;
  2692.  
  2693.     while (n) {
  2694.     /* This sucks. The DIW may end vertically at exactly this point. Therefore,
  2695.      * we must call decide_line(). If we're vertically outside the DIW,
  2696.      * copper_cycle_time will be != -1 after this call [Sanity Interference] */
  2697.     decide_line ();
  2698. #if COPPER_ALTERNATIVE == 1
  2699.     if (current_cycle >= (maxhpos-3)) {
  2700.         n_needed += maxhpos - current_cycle;
  2701.         current_cycle = 0;
  2702.         continue;
  2703.     }
  2704. #endif
  2705.     if (copper_cycle_time == -1 && current_cycle >= 0x14 
  2706.         && current_cycle >= plfstrt && current_cycle < plfstrt + plflinelen
  2707.         && (planes == 6 || (planes == 5 && (current_cycle % 8) < 4)))
  2708.     {
  2709.         n_needed += 4;
  2710.         current_cycle += 4;
  2711.     } else {
  2712.         n_needed += 2;
  2713.         current_cycle += 2;        
  2714.     }
  2715.     if (current_cycle >= maxhpos)
  2716.         current_cycle -= maxhpos;
  2717.     n--;
  2718.     }
  2719.     return n_needed;
  2720. }
  2721.  
  2722. static __inline__ int calc_copper_cycles (int n_cycles)
  2723. {
  2724.     return /*copper_cycle_time != -1 ? copper_cycle_time * n_cycles : */copper_memory_cycles (n_cycles);
  2725. }
  2726.  
  2727. static __inline__ int copper_init_read (int n_cycles)
  2728. {
  2729.     if (dmaen(DMA_COPPER)){
  2730.     int t = calc_copper_cycles (n_cycles);
  2731.  
  2732.     eventtab[ev_copper].evtime = t + cycles;
  2733.     return 1;
  2734.     } else {
  2735.     copstate = COP_read;
  2736.     eventtab[ev_copper].active = 0;
  2737.     return 0;
  2738.     }
  2739. }
  2740.  
  2741. static __inline__ void copper_read (void)
  2742. {
  2743.     int cmd;
  2744.     
  2745.     copi1 = chipmem_bank.wget(coplc); 
  2746.     copi2 = chipmem_bank.wget(coplc+2);
  2747.     coplc += 4;
  2748.     eventtab[ev_copper].oldcycles = cycles;
  2749.     
  2750.     cmd = (copi1 & 1) | ((copi2 & 1) << 1);
  2751.     copstate = cop_cmds[cmd];
  2752.     eventtab[ev_copper].oldcycles = cycles;
  2753. }
  2754.  
  2755. static __inline__ void handle_bltfinish_wait (void)
  2756. {
  2757.     if (bltstate == BLT_done) {
  2758.     copstate = COP_read;
  2759.     /* Don't need to wait. Experimental: No copper wakeup time in this case. */
  2760.     } else {
  2761.     eventtab[ev_copper].active = 0;
  2762.     copstate = COP_morewait;
  2763.     copper_waiting_for_blitter = 1;
  2764.     }
  2765. }
  2766.  
  2767. void blitter_done_notify (void)
  2768. {
  2769.     if (copper_waiting_for_blitter) {
  2770.     copper_waiting_for_blitter = 0;
  2771.     eventtab[ev_copper].active = 1;
  2772.     eventtab[ev_copper].oldcycles = cycles;
  2773.     eventtab[ev_copper].evtime = 1 + cycles;
  2774.     events_schedule ();
  2775.     }
  2776. }
  2777.  
  2778. static void do_copper_cheat(void)
  2779. {
  2780.     int coptime, t;
  2781.     int nmoves = 100; /*??*/
  2782.     int nextcycles = eventtab[ev_hsync].evtime + currprefs.copper_pos;
  2783.  
  2784.     eventtab[ev_copper].evtime = nextcycles;
  2785.     eventtab[ev_copper].oldcycles = cycles;
  2786.     nextcycles -= cycles;
  2787.  
  2788.     if (!dmaen(DMA_COPPER)) {
  2789.     eventtab[ev_copper].active = 0;
  2790.     return;
  2791.     }
  2792.     for (; nmoves; nmoves--)
  2793.     switch(copstate){
  2794.      case COP_read:
  2795.         copper_read ();
  2796.         break;
  2797.  
  2798.      case COP_read_ignore:
  2799.         copper_read ();
  2800.         copstate = COP_read;
  2801.         break;
  2802.  
  2803.      case COP_move:
  2804.         if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
  2805.         custom_bank.wput(copi1,copi2);
  2806.         copstate = COP_read;
  2807.         } else {
  2808.         copstate = COP_stop;
  2809.         eventtab[ev_copper].active = 0;
  2810.         copper_active = 0;
  2811.         return;
  2812.         }
  2813.         break;
  2814.  
  2815.      case COP_skip:
  2816.         copstate = COP_read;
  2817.         if (calc_copcomp_true(vpos, current_hpos()) == 0)
  2818.         copstate = COP_read_ignore;
  2819.         break;
  2820.  
  2821.      case COP_wait:
  2822.         coptime = calc_copcomp_true(vpos, current_hpos());
  2823.         if (coptime < 0) {
  2824.         copstate = COP_stop;
  2825.         eventtab[ev_copper].active = 0;
  2826.         copper_active = 0;
  2827.         return;
  2828.         }
  2829.         if (coptime == 0) {
  2830.         copper_read();
  2831.         if (vpos != 255)
  2832.             break;
  2833.         eventtab[ev_copper].evtime = cycles + 6;
  2834.         return;
  2835.         }
  2836.         if (coptime >= nextcycles)
  2837.         return;
  2838.         if (vpos == 255)
  2839.         eventtab[ev_copper].evtime = cycles + coptime;
  2840.         /*else
  2841.         copstate = COP_read;*/
  2842.         return;
  2843.  
  2844.      case COP_stop:
  2845.         eventtab[ev_copper].active = 0;
  2846.         copper_active = 0;
  2847.         return;
  2848.         
  2849.      case COP_morewait:
  2850.      case COP_do_read:
  2851.      case COP_do_read_ignore:
  2852.         abort();
  2853.     }
  2854. }
  2855.  
  2856. static void do_copper(void)
  2857. {
  2858.     int coptime, t;
  2859.     for (;;)
  2860.     switch(copstate){
  2861.      case COP_read:
  2862.         eventtab[ev_copper].oldcycles = cycles;
  2863.         if (!copper_init_read (2))
  2864.         return;
  2865.         copstate = COP_do_read;
  2866.         return;
  2867.     
  2868.      case COP_do_read:
  2869.         copper_read ();
  2870.         break;
  2871.  
  2872.      case COP_read_ignore:
  2873.         eventtab[ev_copper].oldcycles = cycles;
  2874.         if (!copper_init_read (2))
  2875.         return;
  2876.         copstate = COP_do_read_ignore;
  2877.         return;
  2878.  
  2879.      case COP_do_read_ignore:
  2880.         copper_read ();
  2881.         copstate = COP_read;
  2882.         break;
  2883.  
  2884.      case COP_move:
  2885.         if (copi1 >= (copcon & 2 ? 0x40u : 0x80u)) {
  2886.         custom_bank.wput(copi1,copi2);
  2887.         copstate = COP_read;
  2888.         break;
  2889.         } else {
  2890.         copstate = COP_stop;
  2891.         eventtab[ev_copper].active = 0;
  2892.         copper_active = 0;
  2893.         }
  2894.         return;
  2895.  
  2896.      case COP_skip:
  2897.         copstate = COP_read;
  2898.         if (calc_copcomp_true(vpos, current_hpos()) == 0)
  2899.         copstate = COP_read_ignore;
  2900.         break;
  2901.  
  2902.      case COP_wait:
  2903.         /* Recognize blitter wait statements. This is a speed optimization
  2904.          * only.*/
  2905.         if (copi1 == 1 && copi2 == 0) {
  2906.         handle_bltfinish_wait ();
  2907.         if (!eventtab[ev_copper].active)
  2908.             return;
  2909.         break;
  2910.         }
  2911.         coptime = calc_copcomp_true_vpos(vpos, current_hpos());
  2912.         if (coptime > 0) {
  2913.         copstate = COP_morewait;
  2914.         eventtab[ev_copper].oldcycles = cycles;
  2915.         eventtab[ev_copper].evtime = coptime + cycles;
  2916.         return;
  2917.         }
  2918.         coptime = calc_copcomp_true(vpos, current_hpos());
  2919.         if (coptime < 0) {
  2920.         copstate = COP_stop;
  2921.         eventtab[ev_copper].active = 0;
  2922.         copper_active = 0;
  2923.         return;
  2924.         }
  2925.         if (coptime) {
  2926.         copstate = COP_morewait;
  2927.         eventtab[ev_copper].evtime = coptime + cycles;
  2928.         return;
  2929.         }
  2930.         copstate = COP_read;
  2931.         /* Experimental: no copper wakeup time in this case. The HRM says
  2932.          * nothing about this. */
  2933.         break;
  2934.  
  2935.      case COP_morewait:
  2936.         coptime = calc_copcomp_true(vpos, current_hpos());
  2937.         if (coptime < 0) {
  2938.         copstate = COP_stop;
  2939.         eventtab[ev_copper].active = 0;
  2940.         copper_active = 0;
  2941.         return;
  2942.         }
  2943.         if (coptime) {
  2944.         eventtab[ev_copper].evtime = coptime + cycles;
  2945.         return;
  2946.         }
  2947.         /* Copper wakeup time: 1 memory cycle, plus 2 for the next read */
  2948.         eventtab[ev_copper].oldcycles = cycles;
  2949.         if (!copper_init_read (3))
  2950.         return;
  2951.         copstate = COP_do_read;
  2952.         return;
  2953.  
  2954.      case COP_stop:
  2955.         eventtab[ev_copper].active = 0;
  2956.         copper_active = 0;
  2957.         return;
  2958.     }
  2959. }
  2960.  
  2961. static void diskblk_handler(void)
  2962. {
  2963.     regs.spcflags |= SPCFLAG_DISK;
  2964.     eventtab[ev_diskblk].active = 0;
  2965. }
  2966.  
  2967. void do_disk(void)
  2968. {
  2969.     if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) {
  2970.     static int warned = 0;
  2971.     if (!warned)
  2972.         warned++, write_log ("BUG!\n");
  2973.     return;
  2974.     }
  2975.     if (dmaen(0x10)){
  2976.     if (dsklen & 0x4000) {
  2977.         if (!chipmem_bank.check (dskpt, 2*dsklength)) {
  2978.         write_log ("warning: Bad disk write DMA pointer\n");
  2979.         } else {
  2980.         uae_u8 *mfmp = get_real_address (dskpt);
  2981.         int i;
  2982.         DISK_InitWrite();
  2983.  
  2984.         for (i = 0; i < dsklength; i++) {
  2985.             uae_u16 d = (*mfmp << 8) + *(mfmp+1);
  2986.             mfmwrite[i] = d;
  2987.             mfmp += 2;
  2988.         }
  2989.         DISK_WriteData(dsklength);
  2990.         }
  2991.     } else {
  2992.         int result = DISK_ReadMFM (dskpt);
  2993.     }
  2994.     regs.spcflags &= ~SPCFLAG_DISK;
  2995.     INTREQ(0x9002);
  2996.     dskdmaen = -1;
  2997.     }
  2998. }
  2999.  
  3000. static void gen_pfield_tables(void)
  3001. {
  3002.     int i;
  3003.     union {
  3004.     struct {
  3005.         uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
  3006.     } foo;
  3007.     struct {
  3008.         uae_u32 a, b, c, d;
  3009.     } bar;
  3010.     } baz;
  3011.     
  3012.     for (i = 0; i < 256; i++) {
  3013.     /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
  3014.     baz.foo.a = i & 64 ? 1 : 0;
  3015.     baz.foo.b = i & 16 ? 1 : 0;
  3016.     baz.foo.c = i & 4 ? 1 : 0;
  3017.     baz.foo.d = i & 1 ? 1 : 0;
  3018.     hirestab_l[i][0] = baz.bar.a;
  3019.     
  3020.     baz.foo.a = i & 128 ? 1 : 0;
  3021.     baz.foo.b = i & 64 ? 1 : 0;
  3022.     baz.foo.c = i & 32 ? 1 : 0;
  3023.     baz.foo.d = i & 16 ? 1 : 0;
  3024.     baz.foo.e = i & 8 ? 1 : 0;
  3025.     baz.foo.f = i & 4 ? 1 : 0;
  3026.     baz.foo.g = i & 2 ? 1 : 0;
  3027.     baz.foo.h = i & 1 ? 1 : 0;
  3028.     lorestab_l[i][0] = baz.bar.a;
  3029.     lorestab_l[i][1] = baz.bar.b;
  3030.     sprtaba[i] = ((((i >> 7) & 1) << 0)
  3031.               | (((i >> 6) & 1) << 2)
  3032.               | (((i >> 5) & 1) << 4)
  3033.               | (((i >> 4) & 1) << 6)
  3034.               | (((i >> 3) & 1) << 8)
  3035.               | (((i >> 2) & 1) << 10)
  3036.               | (((i >> 1) & 1) << 12)
  3037.               | (((i >> 0) & 1) << 14));
  3038.     sprtabb[i] = sprtaba[i] * 2;
  3039.     clxtab[i] = ((((i & 3) && (i & 12)) << 9)
  3040.              | (((i & 3) && (i & 48)) << 10)
  3041.              | (((i & 3) && (i & 192)) << 11)
  3042.              | (((i & 12) && (i & 48)) << 12)
  3043.              | (((i & 12) && (i & 192)) << 13)
  3044.              | (((i & 48) && (i & 192)) << 14));
  3045.     }
  3046.     
  3047.     for (i = 0; i < 256; i++) {
  3048.     baz.foo.a = i & 128 ? 1 : 0;
  3049.     baz.foo.b = i & 64 ? 1 : 0;
  3050.     baz.foo.c = i & 32 ? 1 : 0;
  3051.     baz.foo.d = i & 16 ? 1 : 0;
  3052.     baz.foo.e = i & 8 ? 1 : 0;
  3053.     baz.foo.f = i & 4 ? 1 : 0;
  3054.     baz.foo.g = i & 2 ? 1 : 0;
  3055.     baz.foo.h = i & 1 ? 1 : 0;
  3056.     hirestab_h[i][0] = baz.bar.a;
  3057.     hirestab_h[i][1] = baz.bar.b;
  3058.     
  3059.     baz.foo.a = i & 128 ? 1 : 0;
  3060.     baz.foo.b = i & 128 ? 1 : 0;
  3061.     baz.foo.c = i & 64 ? 1 : 0;
  3062.     baz.foo.d = i & 64 ? 1 : 0;
  3063.     baz.foo.e = i & 32 ? 1 : 0;
  3064.     baz.foo.f = i & 32 ? 1 : 0;
  3065.     baz.foo.g = i & 16 ? 1 : 0;
  3066.     baz.foo.h = i & 16 ? 1 : 0;
  3067.     baz.foo.i = i & 8 ? 1 : 0;
  3068.     baz.foo.j = i & 8 ? 1 : 0;
  3069.     baz.foo.k = i & 4 ? 1 : 0;
  3070.     baz.foo.l = i & 4 ? 1 : 0;
  3071.     baz.foo.m = i & 2 ? 1 : 0;
  3072.     baz.foo.n = i & 2 ? 1 : 0;
  3073.     baz.foo.o = i & 1 ? 1 : 0;
  3074.     baz.foo.p = i & 1 ? 1 : 0;
  3075.     lorestab_h[i][0] = baz.bar.a;
  3076.     lorestab_h[i][1] = baz.bar.b;
  3077.     lorestab_h[i][2] = baz.bar.c;
  3078.     lorestab_h[i][3] = baz.bar.d;
  3079.     }
  3080. }
  3081.  
  3082. static void do_sprites(int currvp, int currhp)
  3083. {   
  3084.     int i;
  3085.     /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is
  3086.      * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */
  3087.     int maxspr = currhp/4 - 0x14/4;
  3088. #if 0
  3089.     if (currvp == 0)
  3090.     return;
  3091. #else 
  3092.     /* I don't know whether this is right. Some programs write the sprite pointers
  3093.      * directly at the start of the copper list. With the currvp==0 check, the
  3094.      * first two words of data are read on the second line in the frame. The problem
  3095.      * occurs when the program jumps to another copperlist a few lines further down
  3096.      * which _also_ writes the sprite pointer registers. This means that a) writing
  3097.      * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
  3098.      * is disabled until the end of the vertical blanking interval. The HRM
  3099.      * isn't clear - it says that the vertical sprite position can be set to any
  3100.      * value, but this wouldn't be the first mistake... */
  3101.     /* Update: I modified one of the programs to write the sprite pointers the 
  3102.      * second time only _after_ the VBlank interval, and it showed the same behaviour
  3103.      * as it did unmodified under UAE with the above check. This indicates that the
  3104.      * solution below is correct. */
  3105.     if (currvp < vblank_endline)
  3106.     return;
  3107. #endif
  3108.     if (maxspr < 0)
  3109.     return;
  3110.     if (maxspr > 8)
  3111.     maxspr = 8;
  3112.  
  3113.     for (i = 0; i < maxspr; i++) {
  3114.     int fetch = 0;
  3115.  
  3116.     if (spron[i] == 0)
  3117.         continue;
  3118.  
  3119.     if (sprst[i] == SPR_restart) {
  3120.         fetch = 2;
  3121.         spron[i] = 1;
  3122.     } else if ((sprst[i] == SPR_waiting_start && sprvstart[i] == vpos) || sprst[i] == SPR_waiting_stop) {
  3123.         fetch = 1;
  3124.         sprst[i] = SPR_waiting_stop;
  3125.     }
  3126.     if (sprst[i] == SPR_waiting_stop && sprvstop[i] == vpos) {
  3127.         fetch = 2;
  3128.         sprst[i] = SPR_waiting_start;
  3129.     }
  3130.  
  3131.     if (fetch && dmaen(DMA_SPRITE)) {
  3132.         uae_u16 data1 = chipmem_bank.wget(sprpt[i]);
  3133.         uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2);
  3134.         sprpt[i] += 4;
  3135.         
  3136.         if (fetch == 1) {
  3137.         /* Hack for X mouse auto-calibration */
  3138.         if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) {
  3139.             spr0ctl=sprctl[0];
  3140.             spr0pos=sprpos[0];
  3141.             sprvbfl=2;
  3142.         }
  3143.         SPRxDATB_1(data2, i);
  3144.         SPRxDATA_1(data1, i);
  3145.         } else {
  3146.         SPRxPOS_1(data1, i);
  3147.         SPRxCTL_1(data2, i);
  3148.         }
  3149.     }
  3150.     }
  3151. }
  3152.  
  3153. static uae_u32 attach_2nd;
  3154.  
  3155. static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
  3156. {
  3157.     int j;
  3158.     int sprxp = spd[i].linepos;
  3159.     uae_u32 datab = spd[i].datab;
  3160.     uae_u32 mask2 = 0;
  3161.     int sbit = 1 << spd[i].num;
  3162.     int sprx_shift = 1;
  3163.     int attach_compare = -1;
  3164.     if (currprefs.gfx_lores != 1)
  3165.     sprx_shift = 0;
  3166.  
  3167.     attach_2nd = 0;
  3168.     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
  3169.     attach_compare = spd[i].num - 1;
  3170.  
  3171.     for (j = prev_overlap; j < i; j++) {
  3172.     uae_u32 mask1;
  3173.     int off;
  3174.     
  3175.     if (spd[i].num < spd[j].num)
  3176.         continue;
  3177.  
  3178.     off = sprxp - spd[j].linepos;
  3179.     off <<= sprx_shift;
  3180.     mask1 = spd[j].datab >> off;
  3181.  
  3182.     /* If j is an attachment for i, then j doesn't block i */
  3183.     if (spd[j].num == attach_compare) {
  3184.         attach_2nd |= mask1;
  3185.     } else {
  3186.         mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
  3187.         mask1 |= (mask1 & 0x55555555) << 1;
  3188.         if (datab & mask1)
  3189.         clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
  3190.         mask2 |= mask1;
  3191.     }
  3192.     }
  3193.     for (j = i+1; j < nr_spr; j++) {
  3194.     uae_u32 mask1;
  3195.     int off = spd[j].linepos - sprxp;
  3196.  
  3197.     if (off >= sprite_width || spd[i].num < spd[j].num)
  3198.         break;
  3199.  
  3200.     off <<= sprx_shift;
  3201.     mask1 = spd[j].datab << off;
  3202.  
  3203.     /* If j is an attachment for i, then j doesn't block i */
  3204.     if (spd[j].num == attach_compare) {
  3205.         attach_2nd |= mask1;
  3206.     } else {
  3207.         mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
  3208.         mask1 |= (mask1 & 0x55555555) << 1;
  3209.         if (datab & mask1)
  3210.         clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
  3211.         mask2 |= mask1;
  3212.     }
  3213.     }
  3214.     datab &= ~mask2;
  3215.     return datab;
  3216. }
  3217.  
  3218. static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
  3219. {
  3220.     uae_u32 datcd;
  3221.     int basecol = 16;
  3222.     if (!attch)
  3223.     basecol += (spr & ~1)*2;
  3224.     if (bpldualpf)
  3225.     basecol |= 128;
  3226.     if (attch)
  3227.     datcd = attach_2nd;
  3228.  
  3229.     for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
  3230.     int col;
  3231.  
  3232.     if (attch) {
  3233.         col = ((datab & 3) << 2) | (datcd & 3);
  3234.         datcd >>= 2;
  3235.     } else
  3236.         col = datab & 3;
  3237.     datab >>= 2;
  3238.     if (col) {
  3239.         col |= basecol;
  3240.         if (ham) {
  3241.         col = colors_for_drawing.color_regs[col];
  3242.         ham_linebuf[sprxp] = col;
  3243.         if (sprx_inc == 2) {
  3244.             ham_linebuf[sprxp+1] = col;
  3245.         }
  3246.         } else {
  3247.         pixdata.apixels[sprxp] = col;
  3248.         if (sprx_inc == 2) {
  3249.             pixdata.apixels[sprxp+1] = col;
  3250.         }
  3251.         }
  3252.     }
  3253.     }
  3254. }
  3255.  
  3256. static void walk_sprites (struct sprite_draw *spd, int nr_spr)
  3257. {
  3258.     int i, prev_overlap;
  3259.     int last_sprite_pos = -64;
  3260.     uae_u32 plane1 = 0, plane2 = 0;
  3261.     int sprx_inc = 1, sprx_shift = 1;
  3262.     
  3263.     if (currprefs.gfx_lores == 0)
  3264.     sprx_inc = 2, sprx_shift = 0;
  3265.  
  3266.     prev_overlap = 0;
  3267.     for (i = 0; i < nr_spr; i++) {
  3268.     int sprxp = spd[i].linepos;
  3269.     int m = 1 << spd[i].num;
  3270.     uae_u32 datab;
  3271.     while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
  3272.         prev_overlap++;
  3273.     
  3274.     datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
  3275. #ifdef LORES_HACK
  3276.     if (currprefs.gfx_lores == 2)
  3277.         sprxp >>= 1;
  3278. #endif
  3279.     if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
  3280.         if (sprxp != last_sprite_pos) {
  3281.         int ok = last_sprite_pos-sprxp+16;
  3282.         int ok2;
  3283.         if (ok <= 0) {
  3284.             ok = ok2 = 0;
  3285.             plane1 = 0;
  3286.             plane2 = 0;
  3287.         } else {
  3288.             ok2 = ok << sprx_shift;
  3289.             plane1 >>= 32 - ok2;
  3290.             plane2 >>= 32 - ok2;
  3291.         }
  3292.         last_sprite_pos = sprxp;
  3293.  
  3294.         if (bpldualpf) {
  3295.             uae_u32 mask = 3 << ok2;
  3296.             int p = sprxp+ok;
  3297.  
  3298.             for (; mask; mask <<= 2, p += sprx_inc) {
  3299.             int data = pixdata.apixels[p];
  3300.             if (dblpf_2nd2[data] == 2)
  3301.                 plane2 |= mask;
  3302.             if (dblpf_2nd1[data] == 1)
  3303.                 plane1 |= mask;
  3304.             }
  3305.         } else {
  3306.             uae_u32 mask = 3 << ok2;
  3307.             int p = sprxp+ok;
  3308.  
  3309.             for (; mask; mask <<= 2, p += sprx_inc) {
  3310.             if (pixdata.apixels[p])
  3311.                 plane2 |= mask;
  3312.             }
  3313.         }
  3314.         }
  3315.         if (bpldualpf && m >= plfpri[1]) {
  3316.         datab &= ~plane1;
  3317.         attach_2nd &= ~plane1;
  3318.         }
  3319.         if (m >= plfpri[2]) {
  3320.         datab &= ~plane2;
  3321.         attach_2nd &= ~plane2;
  3322.         }
  3323.     }
  3324.     if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
  3325.         /* Attached sprite */
  3326.         if (bplham) {
  3327.         if (sprx_inc == 1) {
  3328.             render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
  3329.         } else {
  3330.             render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
  3331.         }
  3332.         } else {
  3333.         if (sprx_inc == 1) {
  3334.             render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
  3335.         } else {
  3336.             render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
  3337.         }
  3338.         }
  3339.         /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
  3340.         if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
  3341.         i++;
  3342.     } else {
  3343.         if (bplham) {
  3344.         if (sprx_inc == 1) {
  3345.             render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
  3346.         } else {
  3347.             render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
  3348.         }
  3349.         } else {
  3350.         if (sprx_inc == 1) {
  3351.             render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
  3352.         } else {
  3353.             render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
  3354.         }
  3355.         }
  3356.     }
  3357.     }
  3358. }
  3359.  
  3360. #ifndef SMART_UPDATE
  3361. #undef UNALIGNED_PROFITABLE
  3362. #endif
  3363.  
  3364. #ifdef UNALIGNED_PROFITABLE
  3365. /*
  3366.  * Be sure to pass a constant for the third and fourth parameters to get proper optimization.
  3367.  */
  3368. static __inline__ void doop_planes_hires_unaligned_h (uae_u32 *app, uae_u8 *ptr, int nplanes, int do_or)
  3369. {
  3370.     int i;
  3371.     int len = dp_for_drawing->plflinelen >> 1;
  3372.     for (i = 0; i < len; i++) {
  3373.     unsigned int data1;
  3374.     uae_u32 v1, v2;
  3375.  
  3376.     data1 = *(ptr + i);
  3377.     v1 = hirestab_h[data1][0];
  3378.     v2 = hirestab_h[data1][1];
  3379.  
  3380.     if (nplanes > 1) {
  3381.         unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3382.         v1 |= hirestab_h[data2][0] << 2;
  3383.         v2 |= hirestab_h[data2][1] << 2;
  3384.     }
  3385.     if (nplanes > 2) {
  3386.         unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3387.         v1 |= hirestab_h[data3][0] << 4;
  3388.         v2 |= hirestab_h[data3][1] << 4;
  3389.     }
  3390.     if (nplanes > 3) {
  3391.         unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3392.         v1 |= hirestab_h[data4][0] << 6;
  3393.         v2 |= hirestab_h[data4][1] << 6;
  3394.     }
  3395.     if (do_or) {
  3396.         app[i*2] |= v1 << 1;
  3397.         app[i*2 + 1] |= v2 << 1;
  3398.     } else {
  3399.         app[i*2] = v1;
  3400.         app[i*2 + 1] = v2;
  3401.     }
  3402.     }
  3403. }
  3404.  
  3405. static __inline__ void doop_planes_lores_unaligned_h (uae_u32 *app, uae_u8 *ptr, int nplanes, int do_or)
  3406. {
  3407.     int i;
  3408.     int len = dp_for_drawing->plflinelen >> 2;
  3409.     for (i = 0; i < len; i++) {
  3410.     unsigned int data1;
  3411.     uae_u32 v1, v2, v3, v4;
  3412.  
  3413.     data1 = *(ptr + i);
  3414.     v1 = lorestab_h[data1][0];
  3415.     v2 = lorestab_h[data1][1];
  3416.     v3 = lorestab_h[data1][2];
  3417.     v4 = lorestab_h[data1][3];
  3418.  
  3419.     if (nplanes > 1) {
  3420.         unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3421.         v1 |= lorestab_h[data2][0] << 2;
  3422.         v2 |= lorestab_h[data2][1] << 2;
  3423.         v3 |= lorestab_h[data2][2] << 2;
  3424.         v4 |= lorestab_h[data2][3] << 2;
  3425.     }
  3426.  
  3427.     if (nplanes > 2) {
  3428.         unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3429.         v1 |= lorestab_h[data3][0] << 4;
  3430.         v2 |= lorestab_h[data3][1] << 4;
  3431.         v3 |= lorestab_h[data3][2] << 4;
  3432.         v4 |= lorestab_h[data3][3] << 4;
  3433.     }
  3434.  
  3435.     if (nplanes > 3) {
  3436.         unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3437.         v1 |= lorestab_h[data4][0] << 6;
  3438.         v2 |= lorestab_h[data4][1] << 6;
  3439.         v3 |= lorestab_h[data4][2] << 6;
  3440.         v4 |= lorestab_h[data4][3] << 6;
  3441.     }
  3442.     if (do_or) {
  3443.         app[i*4] |= v1 << 1;
  3444.         app[i*4 + 1] |= v2 << 1;
  3445.         app[i*4 + 2] |= v3 << 1;
  3446.         app[i*4 + 3] |= v4 << 1;
  3447.     } else {
  3448.         app[i*4] = v1;
  3449.         app[i*4 + 1] = v2;
  3450.         app[i*4 + 2] = v3;
  3451.         app[i*4 + 3] = v4;
  3452.     }
  3453.     }
  3454. }
  3455.  
  3456. static __inline__ void doop_planes_hires_unaligned_l (uae_u32 *app, uae_u8 *ptr, int nplanes, int do_or)
  3457. {
  3458.     int i;
  3459.     int len = dp_for_drawing->plflinelen >> 1;
  3460.     for (i = 0; i < len; i++) {
  3461.     unsigned int data1;
  3462.     uae_u32 v;
  3463.  
  3464.     data1 = *(ptr + i);
  3465.     v = hirestab_l[data1][0];
  3466.     if (nplanes > 1) {
  3467.         unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3468.         v |= hirestab_l[data2][0] << 2;
  3469.     }
  3470.     if (nplanes > 2) {
  3471.         unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3472.         v |= hirestab_l[data3][0] << 4;
  3473.     }
  3474.     if (nplanes > 3) {
  3475.         unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);    
  3476.         v |= hirestab_l[data4][0] << 6;
  3477.     }
  3478.     if (do_or)
  3479.         app[i] |= v << 1;
  3480.     else
  3481.         app[i] = v;
  3482.     }
  3483. }
  3484.  
  3485. static __inline__ void doop_planes_lores_unaligned_l (uae_u32 *app, uae_u8 *ptr, int nplanes, int do_or)
  3486. {
  3487.     int i;
  3488.     int len = dp_for_drawing->plflinelen >> 2;
  3489.     for (i = 0; i < len; i++) {
  3490.     unsigned int data1;
  3491.     uae_u32 v1, v2;
  3492.  
  3493.     data1 = *(ptr + i);
  3494.     v1 = lorestab_l[data1][0];
  3495.     v2 = lorestab_l[data1][1];
  3496.  
  3497.     if (nplanes > 1) {
  3498.         unsigned int data2 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3499.         v1 |= lorestab_l[data2][0] << 2;
  3500.         v2 |= lorestab_l[data2][1] << 2;
  3501.     }
  3502.     if (nplanes > 2) {
  3503.         unsigned int data3 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3504.         v1 |= lorestab_l[data3][0] << 4;
  3505.         v2 |= lorestab_l[data3][1] << 4;
  3506.     }
  3507.     if (nplanes > 3) {
  3508.         unsigned int data4 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3509.         v1 |= lorestab_l[data4][0] << 6;
  3510.         v2 |= lorestab_l[data4][1] << 6;
  3511.     }
  3512.     if (do_or) {
  3513.         app[i*2] |= v1 << 1;
  3514.         app[i*2 + 1] |= v2 << 1;
  3515.     } else {
  3516.         app[i*2] = v1;
  3517.         app[i*2 + 1] = v2;
  3518.     }
  3519.     }
  3520. }
  3521.  
  3522. static __inline__ void set_planes_hires_unaligned_h (uae_u32 *app, uae_u8 *ptr, int nplanes)
  3523. {
  3524.     int i;
  3525.     int len = dp_for_drawing->plflinelen >> 1;
  3526.     for (i = 0; i < len; i++) {
  3527.     unsigned int data1;
  3528.     uae_u32 v1, v2;
  3529.  
  3530.     data1 = *(ptr + i);
  3531.     v1 = hirestab_h[data1][0];
  3532.     v2 = hirestab_h[data1][1];
  3533.  
  3534.     if (nplanes > 1) { 
  3535.         unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2);
  3536.         v1 |= hirestab_h[data2][0] << 1;
  3537.         v2 |= hirestab_h[data2][1] << 1;
  3538.     }
  3539.  
  3540.     if (nplanes > 2) { 
  3541.         unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3542.         v1 |= hirestab_h[data3][0] << 2;
  3543.         v2 |= hirestab_h[data3][1] << 2;
  3544.     }
  3545.  
  3546.     if (nplanes > 3) { 
  3547.         unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2);
  3548.         v1 |= hirestab_h[data4][0] << 3;
  3549.         v2 |= hirestab_h[data4][1] << 3;
  3550.     }
  3551.  
  3552.     if (nplanes > 4) { 
  3553.         unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3554.         v1 |= hirestab_h[data5][0] << 4;
  3555.         v2 |= hirestab_h[data5][1] << 4;
  3556.     }
  3557.  
  3558.     if (nplanes > 5) { 
  3559.         unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2);
  3560.         v1 |= hirestab_h[data6][0] << 5;
  3561.         v2 |= hirestab_h[data6][1] << 5;
  3562.     }
  3563.  
  3564.     if (nplanes > 6) { 
  3565.         unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3566.         v1 |= hirestab_h[data7][0] << 6;
  3567.         v2 |= hirestab_h[data7][1] << 6;
  3568.     }
  3569.  
  3570.     if (nplanes > 7) { 
  3571.         unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2);    
  3572.          v1 |= hirestab_h[data8][0] << 7;
  3573.          v2 |= hirestab_h[data8][1] << 7;
  3574.     }
  3575.     app[i*2] = v1;
  3576.     app[i*2 + 1] = v2;
  3577.     }
  3578. }
  3579.  
  3580. static __inline__ void set_planes_lores_unaligned_h (uae_u32 *app, uae_u8 *ptr, int nplanes)
  3581. {
  3582.     int i;
  3583.     int len = dp_for_drawing->plflinelen >> 2;
  3584.     for (i = 0; i < len; i++) {
  3585.     unsigned int data1;
  3586.     uae_u32 v1, v2, v3, v4;
  3587.  
  3588.     data1 = *(ptr + i);
  3589.     v1 = lorestab_h[data1][0];
  3590.     v2 = lorestab_h[data1][1];
  3591.     v3 = lorestab_h[data1][2];
  3592.     v4 = lorestab_h[data1][3];
  3593.  
  3594.     if (nplanes > 1) { 
  3595.         unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2);
  3596.         v1 |= lorestab_h[data2][0] << 1;
  3597.         v2 |= lorestab_h[data2][1] << 1;
  3598.         v3 |= lorestab_h[data2][2] << 1;
  3599.         v4 |= lorestab_h[data2][3] << 1;
  3600.     }
  3601.  
  3602.     if (nplanes > 2) {
  3603.         unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3604.         v1 |= lorestab_h[data3][0] << 2;
  3605.         v2 |= lorestab_h[data3][1] << 2;
  3606.         v3 |= lorestab_h[data3][2] << 2;
  3607.         v4 |= lorestab_h[data3][3] << 2;
  3608.     }
  3609.  
  3610.     if (nplanes > 3) {
  3611.         unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2);
  3612.         v1 |= lorestab_h[data4][0] << 3;
  3613.         v2 |= lorestab_h[data4][1] << 3;
  3614.         v3 |= lorestab_h[data4][2] << 3;
  3615.         v4 |= lorestab_h[data4][3] << 3;
  3616.     }
  3617.  
  3618.     if (nplanes > 4) { 
  3619.         unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3620.         v1 |= lorestab_h[data5][0] << 4;
  3621.         v2 |= lorestab_h[data5][1] << 4;
  3622.         v3 |= lorestab_h[data5][2] << 4;
  3623.         v4 |= lorestab_h[data5][3] << 4;
  3624.     }
  3625.  
  3626.     if (nplanes > 5) {
  3627.         unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2);
  3628.         v1 |= lorestab_h[data6][0] << 5;
  3629.         v2 |= lorestab_h[data6][1] << 5;
  3630.         v3 |= lorestab_h[data6][2] << 5;
  3631.         v4 |= lorestab_h[data6][3] << 5;
  3632.     }
  3633.  
  3634.     if (nplanes > 6) {
  3635.         unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3636.         v1 |= lorestab_h[data7][0] << 6;
  3637.         v2 |= lorestab_h[data7][1] << 6;
  3638.         v3 |= lorestab_h[data7][2] << 6;
  3639.         v4 |= lorestab_h[data7][3] << 6;
  3640.     }
  3641.  
  3642.     if (nplanes > 7) {
  3643.         unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2);
  3644.         v1 |= lorestab_h[data8][0] << 7;
  3645.         v2 |= lorestab_h[data8][1] << 7;
  3646.         v3 |= lorestab_h[data8][2] << 7;
  3647.         v4 |= lorestab_h[data8][3] << 7;
  3648.     }
  3649.     app[i*4] = v1;
  3650.     app[i*4 + 1] = v2;
  3651.     app[i*4 + 2] = v3;
  3652.     app[i*4 + 3] = v4;
  3653.     }
  3654. }
  3655.  
  3656. static __inline__ void set_planes_hires_unaligned_l (uae_u32 *app, uae_u8 *ptr, int nplanes)
  3657. {
  3658.     int i;
  3659.     int len = dp_for_drawing->plflinelen >> 1;
  3660.     for (i = 0; i < len; i++) {
  3661.     unsigned int data1;
  3662.     uae_u32 v;
  3663.  
  3664.     data1 = *(ptr + i);
  3665.     
  3666.     v = hirestab_l[data1][0];
  3667.     if (nplanes > 1) {
  3668.         unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2);
  3669.         v |= hirestab_l[data2][0] << 1;
  3670.     }
  3671.     if (nplanes > 2) {
  3672.         unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3673.         v |= hirestab_l[data3][0] << 2;
  3674.     }
  3675.     if (nplanes > 3) {
  3676.         unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2);
  3677.         v |= hirestab_l[data4][0] << 3;
  3678.     }
  3679.     if (nplanes > 4) {
  3680.         unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3681.         v |= hirestab_l[data5][0] << 4;
  3682.     }
  3683.     if (nplanes > 5) {
  3684.         unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2);
  3685.         v |= hirestab_l[data6][0] << 5;
  3686.     }
  3687.     if (nplanes > 6) {
  3688.         unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3689.         v |= hirestab_l[data7][0] << 6;
  3690.     }
  3691.     if (nplanes > 7) {
  3692.         unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2);
  3693.         v |= hirestab_l[data8][0] << 7;
  3694.     }
  3695.     app[i] = v;
  3696.     }
  3697. }
  3698.  
  3699. static __inline__ void set_planes_lores_unaligned_l (uae_u32 *app, uae_u8 *ptr, int nplanes)
  3700. {
  3701.     int i;
  3702.     int len = dp_for_drawing->plflinelen >> 2;
  3703.     for (i = 0; i < len; i++) {
  3704.     unsigned int data1;
  3705.     uae_u32 v1, v2;
  3706.  
  3707.     data1 = *(ptr + i);
  3708.     v1 = lorestab_l[data1][0];
  3709.     v2 = lorestab_l[data1][1];
  3710.  
  3711.     if (nplanes > 1) {
  3712.         unsigned int data2 = *(ptr + i + 1*MAX_WORDS_PER_LINE*2);
  3713.         v1 |= lorestab_l[data2][0] << 1;
  3714.         v2 |= lorestab_l[data2][1] << 1;
  3715.     }
  3716.  
  3717.     if (nplanes > 2) {
  3718.         unsigned int data3 = *(ptr + i + 2*MAX_WORDS_PER_LINE*2);
  3719.         v1 |= lorestab_l[data3][0] << 2;
  3720.         v2 |= lorestab_l[data3][1] << 2;
  3721.     }
  3722.  
  3723.     if (nplanes > 3) {
  3724.         unsigned int data4 = *(ptr + i + 3*MAX_WORDS_PER_LINE*2);
  3725.         v1 |= lorestab_l[data4][0] << 3;
  3726.         v2 |= lorestab_l[data4][1] << 3;
  3727.     }
  3728.  
  3729.     if (nplanes > 4) {
  3730.         unsigned int data5 = *(ptr + i + 4*MAX_WORDS_PER_LINE*2);
  3731.         v1 |= lorestab_l[data5][0] << 4;
  3732.         v2 |= lorestab_l[data5][1] << 4;
  3733.     }
  3734.  
  3735.     if (nplanes > 5) {
  3736.         unsigned int data6 = *(ptr + i + 5*MAX_WORDS_PER_LINE*2);    
  3737.         v1 |= lorestab_l[data6][0] << 5;
  3738.         v2 |= lorestab_l[data6][1] << 5;
  3739.     }
  3740.  
  3741.     if (nplanes > 6) {
  3742.         unsigned int data7 = *(ptr + i + 6*MAX_WORDS_PER_LINE*2);
  3743.         v1 |= lorestab_l[data7][0] << 6;
  3744.         v2 |= lorestab_l[data7][1] << 6;
  3745.     }
  3746.     
  3747.     if (nplanes > 7) {
  3748.         unsigned int data8 = *(ptr + i + 7*MAX_WORDS_PER_LINE*2);
  3749.         v1 |= lorestab_l[data8][0] << 7;
  3750.         v2 |= lorestab_l[data8][1] << 7;
  3751.     }
  3752.  
  3753.     app[i*2] = v1;
  3754.     app[i*2 + 1] = v2;
  3755.     }
  3756. }
  3757.  
  3758. static void pfield_doline_unaligned_h (int lineno)
  3759. {
  3760.     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
  3761.     
  3762.     if (bplhires) {
  3763.     int xpos1 = xpos + 16 + bpldelay1*2;
  3764.     int xpos2;
  3765.     uae_u8 *dataptr = line_data[lineno];
  3766.     
  3767.     if (bpldelay1 == bpldelay2) {
  3768.         switch (bplplanecnt) {
  3769.          case 1: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1); break;
  3770.          case 2: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2); break;
  3771.          case 3: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3); break;
  3772.          case 4: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4); break;
  3773.          case 5: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 5); break;
  3774.          case 6: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 6); break;
  3775.          case 7: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 7); break;
  3776.          case 8: set_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 8); break;
  3777.         }
  3778.     } else {
  3779.         switch (bplplanecnt) {
  3780.          case 1: case 2: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1, 0); break;
  3781.          case 3: case 4: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2, 0); break;
  3782.          case 5: case 6: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3, 0); break;
  3783.          case 7: case 8: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4, 0); break;
  3784.         }
  3785.  
  3786.         dataptr += MAX_WORDS_PER_LINE*2;
  3787.         xpos2 = xpos + 16 + bpldelay2*2;
  3788.         switch (bplplanecnt) {
  3789.          case 2: case 3: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 1, 1); break;
  3790.          case 4: case 5: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 2, 1); break;
  3791.          case 6: case 7: doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 3, 1); break;
  3792.          case 8:         doop_planes_hires_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 4, 1); break;
  3793.         }
  3794.     }
  3795.     } else {
  3796.     int xpos1 = xpos + 32 + bpldelay1*2;
  3797.     int xpos2;
  3798.     uae_u8 *dataptr = line_data[lineno];
  3799.  
  3800.     if (bpldelay1 == bpldelay2) {
  3801.         switch (bplplanecnt) {
  3802.          case 1: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1); break;
  3803.          case 2: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2); break;
  3804.          case 3: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3); break;
  3805.          case 4: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4); break;
  3806.          case 5: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 5); break;
  3807.          case 6: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 6); break;
  3808.          case 7: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 7); break;
  3809.          case 8: set_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 8); break;
  3810.         }
  3811.     } else {
  3812.         switch (bplplanecnt) {
  3813.          case 1: case 2: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1, 0); break;
  3814.          case 3: case 4: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2, 0); break;
  3815.          case 5: case 6: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3, 0); break;
  3816.          case 7: case 8: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4, 0); break;
  3817.         }
  3818.         
  3819.         dataptr += MAX_WORDS_PER_LINE*2;
  3820.         xpos2 = xpos + 32 + bpldelay2*2;
  3821.         switch (bplplanecnt) {
  3822.          case 2: case 3: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 1, 1); break;
  3823.          case 4: case 5: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 2, 1); break;
  3824.          case 6: case 7: doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 3, 1); break;
  3825.          case 8:         doop_planes_lores_unaligned_h ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 4, 1); break;
  3826.         }
  3827.     }
  3828.     }
  3829. }
  3830.  
  3831. static void pfield_doline_unaligned_l (int lineno)
  3832. {
  3833.     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
  3834.         
  3835.     if (bplhires) {
  3836.     int xpos1 = xpos + 8 + bpldelay1;
  3837.     int xpos2;
  3838.     uae_u8 *dataptr = line_data[lineno];
  3839.  
  3840.     if (bpldelay1 == bpldelay2) {
  3841.         switch (bplplanecnt) {
  3842.          case 1: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1); break;
  3843.          case 2: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2); break;
  3844.          case 3: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3); break;
  3845.          case 4: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4); break;
  3846.          case 5: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 5); break;
  3847.          case 6: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 6); break;
  3848.          case 7: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 7); break;
  3849.          case 8: set_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 8); break;
  3850.         }
  3851.     } else {
  3852.         switch (bplplanecnt) {
  3853.          case 1: case 2: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1, 0); break;
  3854.          case 3: case 4: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2, 0); break;
  3855.          case 5: case 6: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3, 0); break;
  3856.          case 7: case 8: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4, 0); break;
  3857.         }
  3858.  
  3859.         dataptr += MAX_WORDS_PER_LINE*2;
  3860.         xpos2 = xpos + 8 + bpldelay2;
  3861.         switch (bplplanecnt) {
  3862.          case 2: case 3: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 1, 1); break;
  3863.          case 4: case 5: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 2, 1); break;
  3864.          case 6: case 7: doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 3, 1); break;
  3865.          case 8:         doop_planes_hires_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 4, 1); break;
  3866.         }
  3867.     }
  3868.     } else {
  3869.     int xpos1 = xpos + 16 + bpldelay1;
  3870.     int xpos2;
  3871.     uae_u8 *dataptr = line_data[lineno];
  3872.  
  3873.     if (bpldelay1 == bpldelay2) {
  3874.         switch (bplplanecnt) {
  3875.          case 1: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1); break;
  3876.          case 2: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2); break;
  3877.          case 3: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3); break;
  3878.          case 4: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4); break;
  3879.          case 5: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 5); break;
  3880.          case 6: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 6); break;
  3881.          case 7: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 7); break;
  3882.          case 8: set_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 8); break;
  3883.         }
  3884.     } else {
  3885.         switch (bplplanecnt) {
  3886.          case 1: case 2: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 1, 0); break;
  3887.          case 3: case 4: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 2, 0); break;
  3888.          case 5: case 6: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 3, 0); break;
  3889.          case 7: case 8: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, 4, 0); break;
  3890.         }
  3891.         
  3892.         dataptr += MAX_WORDS_PER_LINE*2;
  3893.         xpos2 = xpos + 16 + bpldelay2;
  3894.         switch (bplplanecnt) {
  3895.          case 2: case 3: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 1, 1); break;
  3896.          case 4: case 5: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 2, 1); break;
  3897.          case 6: case 7: doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 3, 1); break;
  3898.          case 8:         doop_planes_lores_unaligned_l ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, 4, 1); break;
  3899.         }
  3900.     }
  3901.     }
  3902. }
  3903.  
  3904. #define pfield_doline_h pfield_doline_unaligned_h
  3905. #define pfield_doline_l pfield_doline_unaligned_l
  3906.  
  3907. #else /* not UNALIGNED_PROFITABLE */
  3908.  
  3909.  
  3910. static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
  3911. {
  3912.     uae_u32 *pixptr = (uae_u32 *)dp;
  3913.  
  3914.     *pixptr |= hirestab_h[data >> 8][0] << bit;
  3915.     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
  3916.     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
  3917.     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
  3918. }
  3919.  
  3920. static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
  3921. {
  3922.     uae_u32 *pixptr = (uae_u32 *)dp;
  3923.     
  3924.     *pixptr |= lorestab_h[data >> 8][0] << bit;
  3925.     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
  3926.     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
  3927.     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
  3928.     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
  3929.     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
  3930.     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
  3931.     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
  3932. }
  3933.  
  3934. static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
  3935. {
  3936.     uae_u32 *pixptr = (uae_u32 *)dp;
  3937.  
  3938.     *pixptr = hirestab_h[data >> 8][0] << bit;
  3939.     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
  3940.     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
  3941.     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
  3942. }
  3943.  
  3944. static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
  3945. {
  3946.     uae_u32 *pixptr = (uae_u32 *)dp;
  3947.     
  3948.     *pixptr = lorestab_h[data >> 8][0] << bit;
  3949.     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
  3950.     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
  3951.     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
  3952.     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
  3953.     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
  3954.     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
  3955.     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
  3956. }
  3957.  
  3958. static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
  3959. {
  3960.     uae_u32 *pixptr = (uae_u32 *)dp;
  3961.  
  3962.     *pixptr |= hirestab_l[data >> 8][0] << bit;
  3963.     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
  3964. }
  3965.  
  3966. static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
  3967. {
  3968.     uae_u32 *pixptr = (uae_u32 *)dp;
  3969.     
  3970.     *pixptr |= lorestab_l[data >> 8][0] << bit;
  3971.     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
  3972.     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
  3973.     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
  3974. }
  3975.  
  3976. static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
  3977. {
  3978.     uae_u32 *pixptr = (uae_u32 *)dp;
  3979.  
  3980.     *pixptr = hirestab_l[data >> 8][0] << bit;
  3981.     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
  3982. }
  3983.  
  3984. static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
  3985. {
  3986.     uae_u32 *pixptr = (uae_u32 *)dp;
  3987.     
  3988.     *pixptr = lorestab_l[data >> 8][0] << bit;
  3989.     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
  3990.     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
  3991.     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
  3992. }
  3993.  
  3994. #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
  3995.     int i; \
  3996.     unsigned int bpldat1; \
  3997.     uae_u16 data; \
  3998.     unsigned int bpldat2 = 0; \
  3999.     uae_u8 *ptr = (POINTER); \
  4000.     for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
  4001.         bpldat1 = bpldat2; \
  4002.     bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
  4003.         ptr+=2; \
  4004.     data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
  4005.     FUNC(data, app, MULT); \
  4006.     app += P_ADD; \
  4007.     } \
  4008.     data = bpldat2 << (16 - DELAY); \
  4009.     FUNC(data, app, MULT); \
  4010. }
  4011.  
  4012. #ifdef SMART_UPDATE
  4013. #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
  4014. #else
  4015. #define DATA_POINTER(n) (real_bplpt[n])
  4016. #endif
  4017.  
  4018. static void pfield_doline_aligned_h (int lineno)
  4019. {
  4020.     int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
  4021.     
  4022.     if (bplhires) {
  4023.     if (bplplanecnt > 0) {
  4024.         int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
  4025.         int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
  4026.         int delay1 = 2*(bpldelay1 & 7);
  4027.         int delay2 = 2*(bpldelay2 & 7);
  4028.         unsigned char *app = pixdata.apixels + xpos1;
  4029.         uae_u8 *dataptr = line_data[lineno];
  4030.  
  4031.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
  4032.         if (bplplanecnt > 2) {
  4033.         app = pixdata.apixels + xpos1;
  4034.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
  4035.         }
  4036. #if AGA_CHIPSET == 1
  4037.         if (bplplanecnt > 4) {
  4038.         app = pixdata.apixels + xpos1;
  4039.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
  4040.         }
  4041.         if (bplplanecnt > 6) {
  4042.         app = pixdata.apixels + xpos1;
  4043.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
  4044.         }
  4045. #endif
  4046.         if (bplplanecnt > 1) {
  4047.         app = pixdata.apixels + xpos2;
  4048.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
  4049.         }
  4050.         if (bplplanecnt > 3) {
  4051.         app = pixdata.apixels + xpos2;
  4052.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
  4053.         }
  4054. #if AGA_CHIPSET == 1
  4055.         if (bplplanecnt > 5) {
  4056.         app = pixdata.apixels + xpos2;
  4057.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
  4058.         }
  4059.         if (bplplanecnt > 7) {
  4060.         app = pixdata.apixels + xpos2;
  4061.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
  4062.         }
  4063. #endif
  4064.     } else {
  4065.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  4066.     }
  4067.     } else {
  4068.     if (bplplanecnt > 0) {
  4069.         int x = xpos + 32;
  4070.         unsigned char *app = pixdata.apixels + x;
  4071.         uae_u8 *dataptr = line_data[lineno];
  4072.         
  4073.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
  4074.         if (bplplanecnt > 2) {
  4075.         app = pixdata.apixels + x;
  4076.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
  4077.         }
  4078.         if (bplplanecnt > 4) {
  4079.         app = pixdata.apixels + x;
  4080.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
  4081.         }
  4082. #if AGA_CHIPSET == 1
  4083.         if (bplplanecnt > 6) {
  4084.         app = pixdata.apixels + x;
  4085.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
  4086.         }
  4087. #endif
  4088.         if (bplplanecnt > 1) {
  4089.         app = pixdata.apixels + x;
  4090.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
  4091.         }
  4092.         if (bplplanecnt > 3) {
  4093.         app = pixdata.apixels + x;
  4094.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
  4095.         }
  4096.         if (bplplanecnt > 5) {
  4097.         app = pixdata.apixels + x;
  4098.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
  4099.         }
  4100. #if AGA_CHIPSET == 1
  4101.         if (bplplanecnt > 7) {
  4102.         app = pixdata.apixels + x;
  4103.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
  4104.         }
  4105. #endif
  4106.     } else {
  4107.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  4108.     }
  4109.     }
  4110. }
  4111.  
  4112. static void pfield_doline_aligned_l (int lineno)
  4113. {
  4114.     int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
  4115.         
  4116.     if (bplhires) {
  4117.     if (bplplanecnt > 0) {
  4118.         int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
  4119.         int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
  4120.         int delay1 = (bpldelay1 & 7) * 2;
  4121.         int delay2 = (bpldelay2 & 7) * 2;
  4122.         unsigned char *app = pixdata.apixels + xpos1;
  4123.         uae_u8 *dataptr = line_data[lineno];
  4124.         
  4125.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
  4126.         if (bplplanecnt > 2) {
  4127.         app = pixdata.apixels + xpos1;
  4128.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
  4129.         }
  4130. #if AGA_CHIPSET == 1
  4131.         if (bplplanecnt > 4) {
  4132.         app = pixdata.apixels + xpos1;
  4133.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
  4134.         }
  4135.         if (bplplanecnt > 6) {
  4136.         app = pixdata.apixels + xpos1;
  4137.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
  4138.         }
  4139. #endif
  4140.         if (bplplanecnt > 1) {
  4141.         app = pixdata.apixels + xpos2;
  4142.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
  4143.         }
  4144.         if (bplplanecnt > 3) {
  4145.         app = pixdata.apixels + xpos2;
  4146.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
  4147.         }
  4148. #if AGA_CHIPSET == 1
  4149.         if (bplplanecnt > 5) {
  4150.         app = pixdata.apixels + xpos2;
  4151.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
  4152.         }
  4153.         if (bplplanecnt > 7) {
  4154.         app = pixdata.apixels + xpos2;
  4155.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
  4156.         }
  4157. #endif
  4158.     } else {
  4159.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  4160.     }
  4161.     } else {
  4162.     if (bplplanecnt > 0) {
  4163.         int x = xpos + 16;
  4164.         int delay1 = bpldelay1;
  4165.         int delay2 = bpldelay2;
  4166.         unsigned char *app = pixdata.apixels + x;
  4167.         uae_u8 *dataptr = line_data[lineno];
  4168.         
  4169.         DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
  4170.         if (bplplanecnt > 2) {
  4171.         app = pixdata.apixels + x;
  4172.         DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
  4173.         }
  4174.         if (bplplanecnt > 4) {
  4175.         app = pixdata.apixels + x;
  4176.         DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
  4177.         }
  4178. #if AGA_CHIPSET == 1
  4179.         if (bplplanecnt > 6) {
  4180.         app = pixdata.apixels + x;
  4181.         DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
  4182.         }
  4183. #endif
  4184.         if (bplplanecnt > 1) {
  4185.         app = pixdata.apixels + x;
  4186.         DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
  4187.         }
  4188.         if (bplplanecnt > 3) {
  4189.         app = pixdata.apixels + x;
  4190.         DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
  4191.         }
  4192.         if (bplplanecnt > 5) {
  4193.         app = pixdata.apixels + x;
  4194.         DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
  4195.         }
  4196. #if AGA_CHIPSET == 1
  4197.         if (bplplanecnt > 7) {
  4198.         app = pixdata.apixels + x;
  4199.         DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
  4200.         }
  4201. #endif
  4202.     } else {
  4203.         memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
  4204.     }
  4205.     }
  4206. }
  4207.  
  4208. #define pfield_doline_h pfield_doline_aligned_h
  4209. #define pfield_doline_l pfield_doline_aligned_l
  4210.  
  4211. #endif /* UNALIGNED_PROFITABLE */
  4212.  
  4213. static void pfield_adjust_delay (void)
  4214. {
  4215.     int ddf_left = dp_for_drawing->plfstrt;
  4216.     int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
  4217.     int i;
  4218.     
  4219.     for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
  4220.     int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
  4221.     int delay1 = delayreg & 0xF;
  4222.     int delay2 = (delayreg >> 4) & 0xF;
  4223.     int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
  4224.     int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
  4225.     int j;
  4226.     startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
  4227.     stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
  4228.     if (currprefs.gfx_lores == 0)
  4229.         delay1 <<= 1, delay2 <<= 1;
  4230.     else if (currprefs.gfx_lores == 2)
  4231.         startpos >>= 1, stoppos >>= 1;
  4232.     for (j = startpos-1; j >= stoppos; j--) {
  4233.         pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
  4234.     }
  4235.     }
  4236. }
  4237.  
  4238. static void init_hardware_frame (void)
  4239. {
  4240.     int i;
  4241.  
  4242.     for (i = 0; i < 8; i++) {
  4243.     sprst[i] = SPR_stop;
  4244.     spron[i] = 0;
  4245.     }
  4246. #if 0
  4247.     memset(sprpos, 0, sizeof sprpos);
  4248.     memset(sprctl, 0, sizeof sprctl);
  4249. #endif
  4250.  
  4251.     next_lineno = 0;
  4252.     nln_how = 0;
  4253.     diwstate = DIW_waiting_start;
  4254.     hdiwstate = DIW_waiting_start;
  4255. }
  4256.  
  4257. static void setdontcare(void)
  4258. {
  4259.     write_log ("Don't care mouse mode set\n");
  4260.     mousestate = dont_care_mouse;
  4261.     lastspr0x = lastmx; lastspr0y = lastmy;
  4262.     mstepx = defstepx; mstepy = defstepy;
  4263. }
  4264.  
  4265. static void setfollow(void)
  4266. {
  4267.     write_log ("Follow sprite mode set\n");
  4268.     mousestate = follow_mouse;
  4269.     lastdiffx = lastdiffy = 0;
  4270.     sprvbfl = 0;
  4271.     spr0ctl=spr0pos = 0;
  4272.     mstepx = defstepx; mstepy = defstepy;
  4273. }
  4274.  
  4275. uae_u32 mousehack_helper (void)
  4276. {
  4277.     int mousexpos, mouseypos;
  4278.  
  4279.     mousexpos = lastmx + linetoscr_x_adjust;
  4280.     if (lastmy >= gfxvidinfo.maxline)
  4281.     lastmy = gfxvidinfo.maxline-1;
  4282.     mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
  4283.     mouseypos <<= 1;
  4284.     mousexpos <<= (1-lores_shift);
  4285.     mousexpos += 2*DISPLAY_LEFT_SHIFT;
  4286.  
  4287.     switch (m68k_dreg (regs, 0)) {
  4288.      case 0:
  4289.     return ievent_alive ? -1 : needmousehack ();
  4290.      case 1:
  4291.     ievent_alive = 10;
  4292.     return mousexpos;
  4293.      case 2:
  4294.     return mouseypos;
  4295.     }
  4296.     return 0;
  4297. }
  4298.  
  4299. void togglemouse(void)
  4300. {
  4301.     switch(mousestate) {
  4302.      case dont_care_mouse: setfollow(); break;
  4303.      case follow_mouse: setdontcare(); break;
  4304.      default: break; /* Nnnnnghh! */
  4305.     }
  4306. }        
  4307.  
  4308. static __inline__ int adjust(int val)
  4309. {
  4310.     if (val>127)
  4311.     return 127; 
  4312.     else if (val<-127)
  4313.     return -127;
  4314.     return val;
  4315. }
  4316.  
  4317. static void do_mouse_hack(void)
  4318. {
  4319.     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
  4320.     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
  4321.     int diffx, diffy;
  4322.     
  4323.     if (ievent_alive > 0) {
  4324.     mouse_x = mouse_y = 0;
  4325.     return;
  4326.     }
  4327.     switch (mousestate) {
  4328.      case normal_mouse:
  4329.     diffx = lastmx - lastsampledmx;
  4330.     diffy = lastmy - lastsampledmy;
  4331.     if (!newmousecounters) {    
  4332.         if (diffx > 127) diffx = 127;
  4333.         if (diffx < -127) diffx = -127;
  4334.         mouse_x += diffx;
  4335.         if (diffy > 127) diffy = 127;
  4336.         if (diffy < -127) diffy = -127;
  4337.         mouse_y += diffy;
  4338.     }
  4339.     lastsampledmx += diffx; lastsampledmy += diffy;
  4340.     break;
  4341.  
  4342.      case dont_care_mouse:
  4343.     diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
  4344.     diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
  4345.     lastspr0x=lastmx; lastspr0y=lastmy;
  4346.     mouse_x+=diffx; mouse_y+=diffy;
  4347.     break;
  4348.     
  4349.      case follow_mouse:
  4350.     if (sprvbfl && sprvbfl-- >1) {
  4351.         int mousexpos, mouseypos;
  4352.         
  4353.         if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x 
  4354.         && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff)
  4355.         {  
  4356.         int val = (lastdiffx << 16) / (spr0x - lastspr0x);
  4357.         if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
  4358.         }
  4359.         if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
  4360.         && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff) 
  4361.         { 
  4362.         int val = (lastdiffy<<16) / (spr0y-lastspr0y);
  4363.         if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
  4364.         }
  4365.         mousexpos = lastmx + linetoscr_x_adjust;
  4366.         if (lastmy >= gfxvidinfo.maxline)
  4367.         lastmy = gfxvidinfo.maxline-1;
  4368.         mouseypos = native2amiga_line_map[lastmy] + thisframe_y_adjust - minfirstline;
  4369.         mouseypos <<= 1;
  4370.         mousexpos <<= (1-lores_shift);
  4371.         mousexpos += 2*DISPLAY_LEFT_SHIFT;
  4372.         diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16);
  4373.         diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16);
  4374.         lastspr0x=spr0x; lastspr0y=spr0y;
  4375.         lastdiffx=diffx; lastdiffy=diffy;
  4376.         mouse_x+=diffx; mouse_y+=diffy; 
  4377.     }
  4378.     break;
  4379.     }
  4380. }
  4381.  
  4382. static void init_row_map(void)
  4383. {
  4384.     int i;
  4385.     for (i = 0; i < gfxvidinfo.maxline + 1; i++)
  4386.     row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
  4387. }
  4388.  
  4389. /* @@@ Are those still useful? */
  4390.  
  4391. /*
  4392.  * A raster line has been built in the graphics buffer. Tell the graphics code
  4393.  * to do anything necessary to display it.
  4394.  */
  4395. static __inline__ void do_flush_line_1 (int lineno)
  4396. {
  4397.     if (lineno < first_drawn_line)
  4398.     first_drawn_line = lineno;
  4399.     if (lineno > last_drawn_line)
  4400.     last_drawn_line = lineno;
  4401.  
  4402.     if (gfxvidinfo.maxblocklines == 0)
  4403.     flush_line(lineno);
  4404.     else {
  4405.     if ((last_block_line+1) != lineno) {
  4406.         if (first_block_line != -2)
  4407.         flush_block (first_block_line, last_block_line);
  4408.         first_block_line = lineno;
  4409.     }
  4410.     last_block_line = lineno;
  4411.     if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
  4412.         flush_block (first_block_line, last_block_line);
  4413.         first_block_line = last_block_line = -2;
  4414.     }
  4415.     }
  4416. }
  4417.  
  4418. static void do_flush_line (int lineno)
  4419. {
  4420.     /* We don't want to call X libraries from the second thread right now. */
  4421. #ifndef SUPPORT_PENGUINS
  4422.     do_flush_line_1 (lineno);
  4423. #else
  4424.     line_drawn[lineno] = 1;
  4425. #endif
  4426. }
  4427.  
  4428. /*
  4429.  * One Amiga frame has been finished. Tell the graphics code about it.
  4430.  * Note that the actual flush_screen() call is a no-op for all reasonable
  4431.  * systems.
  4432.  */
  4433.  
  4434. static void do_flush_screen (int start, int stop)
  4435. {
  4436.     int i;
  4437. #ifdef SUPPORT_PENGUINS
  4438.     for (i = 0; i < gfxvidinfo.maxline; i++) {
  4439.     if (line_drawn[i])
  4440.         do_flush_line_1 (i);
  4441.     }
  4442. #endif
  4443.     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
  4444.     flush_block (first_block_line, last_block_line);
  4445.     }
  4446.     if (start <= stop)
  4447.     flush_screen (start, stop);
  4448. }
  4449.  
  4450. static void adjust_drawing_colors (int ctable, int bplham)
  4451. {
  4452.     if (drawing_color_matches != ctable) {
  4453.     if (bplham) {
  4454.         memcpy (&colors_for_drawing, curr_color_tables + ctable,
  4455.             sizeof colors_for_drawing);
  4456.         color_match_type = color_match_full;
  4457.     } else {
  4458.         memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
  4459.             sizeof colors_for_drawing.acolors);
  4460.         color_match_type = color_match_acolors;
  4461.     }
  4462.     drawing_color_matches = ctable;
  4463.     } else if (bplham && color_match_type != color_match_full) {
  4464.     memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
  4465.         sizeof colors_for_drawing.color_regs);
  4466.     color_match_type = color_match_full;
  4467.     }
  4468. }
  4469.  
  4470. static __inline__ void adjust_color0_for_color_change (void)
  4471. {
  4472.     drawing_color_matches = -1;
  4473.     if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
  4474.     colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
  4475.     colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
  4476.     }
  4477. }
  4478.  
  4479. static __inline__ void do_color_changes (line_draw_func worker)
  4480. {
  4481.     int lastpos = 0, nextpos, i;
  4482.     struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
  4483.     
  4484.     for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
  4485.     if (i == dip_for_drawing->last_color_change)
  4486.         nextpos = max_diwlastword;
  4487.     else
  4488.         nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
  4489.     worker (lastpos, nextpos);
  4490.     if (i != dip_for_drawing->last_color_change) {
  4491.         colors_for_drawing.color_regs[cc->regno] = cc->value;
  4492.         colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
  4493.     }
  4494.     if (nextpos > lastpos) {
  4495.         lastpos = nextpos;
  4496.         if (lastpos >= linetoscr_right_x)
  4497.         break;
  4498.     }
  4499.     }
  4500. }
  4501.  
  4502. static void pfield_expand_dp_bplcon (void)
  4503. {
  4504.     bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
  4505.     bplplanecnt = (dp_for_drawing->bplcon0 & 0x7000) >> 12;
  4506.     bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
  4507. #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
  4508.                   * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
  4509.     bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
  4510. #else
  4511.     bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
  4512. #endif
  4513.     bpldelay1 = dp_for_drawing->bplcon1 & 0xF; 
  4514.     bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF; 
  4515.     plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
  4516.     plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
  4517.     bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
  4518.     bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
  4519. }
  4520.  
  4521. static __inline__ void pfield_draw_line(int lineno, int gfx_ypos, int follow_ypos)
  4522. {
  4523.     int border = 0;
  4524.     int to_screen = 0;
  4525.     int do_double = 0;
  4526.     
  4527.     dp_for_drawing = 0;
  4528.     dip_for_drawing = 0;
  4529.     switch (linestate[lineno]) {
  4530.      case LINE_AS_PREVIOUS:
  4531.      case LINE_REMEMBERED_AS_PREVIOUS:
  4532.     {
  4533.         static int warned = 0;
  4534.         if (!warned)
  4535.         write_log ("Shouldn't get here... this is a bug.\n"), warned++;
  4536.     }
  4537.     line_decisions[lineno].which = -2;
  4538.     return;
  4539.  
  4540.      case LINE_BORDER_PREV:
  4541.     border = 1;
  4542.     dp_for_drawing = line_decisions + lineno - 1;
  4543.     dip_for_drawing = curr_drawinfo + lineno - 1;
  4544.     break;
  4545.  
  4546.      case LINE_BORDER_NEXT:
  4547.     border = 1;
  4548.     dp_for_drawing = line_decisions + lineno + 1;
  4549.     dip_for_drawing = curr_drawinfo + lineno + 1;
  4550.     break;
  4551.  
  4552.      case LINE_DONE_AS_PREVIOUS:
  4553.     line_decisions[lineno].which = -2;
  4554.     /* fall through */
  4555.      case LINE_DONE:
  4556.     return;
  4557.  
  4558.      case LINE_DECIDED_DOUBLE:
  4559.     line_decisions[lineno+1].which = -2;
  4560.     if (follow_ypos != -1) {
  4561.         do_double = 1;
  4562.         linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
  4563.     }
  4564.     
  4565.     /* fall through */
  4566.      default:
  4567.     dip_for_drawing = curr_drawinfo + lineno;
  4568.     dp_for_drawing = line_decisions + lineno;
  4569.     if (dp_for_drawing->which != 1)
  4570.         border = 1;
  4571.     break;
  4572.     }
  4573.     
  4574.     if (!line_changed[lineno] && !frame_redraw_necessary) {
  4575.     /* The case where we can skip redrawing this line. If this line 
  4576.      * is supposed to be doubled, and the next line is remembered as
  4577.      * having been doubled, then the next line is done as well. */
  4578.     if (do_double) {
  4579.         if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS) {
  4580.         if (gfxvidinfo.linemem == NULL)
  4581.             memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
  4582.         line_decisions[lineno + 1].which = -2;
  4583.         do_flush_line (follow_ypos);
  4584.         }
  4585.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4586.     }
  4587.     linestate[lineno] = LINE_DONE;
  4588.     return;
  4589.     }
  4590.  
  4591.     if (!border) {
  4592.     xlinebuffer = gfxvidinfo.linemem;
  4593.     if (xlinebuffer == NULL)
  4594.         xlinebuffer = row_map[gfx_ypos];
  4595.     xlinebuffer -= linetoscr_x_adjust_bytes;
  4596.     aga_lbufptr = aga_linebuf;
  4597.     
  4598.     pfield_expand_dp_bplcon ();
  4599.  
  4600. #ifdef LORES_HACK
  4601.     if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
  4602.         && dip_for_drawing->nr_color_changes == 0 && !bplham)
  4603.         currprefs.gfx_lores = 2;
  4604. #endif
  4605.     pfield_init_linetoscr ();
  4606.     if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
  4607.         bpldelay1 = bpldelay2 = 0;
  4608.         if (currprefs.gfx_lores)
  4609.         pfield_doline_l (lineno);
  4610.         else
  4611.         pfield_doline_h (lineno);
  4612.         pfield_adjust_delay ();
  4613.     } else {
  4614.         if (currprefs.gfx_lores)
  4615.         pfield_doline_l (lineno);
  4616.         else
  4617.         pfield_doline_h (lineno);
  4618.     }
  4619.  
  4620.     /* Check color0 adjust only if we have color changes - shouldn't happen
  4621.      * otherwise. */
  4622.     adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
  4623.  
  4624.     /* The problem is that we must call decode_ham6() BEFORE we do the
  4625.      * sprites. */
  4626.     if (bplham) {
  4627.         init_ham_decoding(linetoscr_x_adjust);
  4628.         if (dip_for_drawing->nr_color_changes == 0) {
  4629.         /* The easy case: need to do HAM decoding only once for the
  4630.          * full line. */
  4631.         decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
  4632.         } else /* Argh. */ {        
  4633.         adjust_color0_for_color_change ();
  4634.         do_color_changes (decode_ham6);
  4635.         adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
  4636.         }
  4637.     }
  4638.  
  4639.     if (dip_for_drawing->nr_sprites != 0) {
  4640.         int spr;
  4641.         walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
  4642.     }
  4643.     if (dip_for_drawing->nr_color_changes == 0) {
  4644.         pfield_do_linetoscr_full (gfxvidinfo.linemem == NULL ? do_double : 0);
  4645.         do_flush_line (gfx_ypos);
  4646.         linestate[lineno] = LINE_DONE;
  4647.  
  4648.         if (do_double) {
  4649.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4650.         do_flush_line (follow_ypos);
  4651.         }
  4652.     } else {
  4653.         int lastpos = 0, nextpos, i;
  4654.  
  4655.         adjust_color0_for_color_change ();
  4656.         do_color_changes (pfield_do_linetoscr);
  4657.  
  4658.         linestate[lineno] = LINE_DONE;
  4659.         do_flush_line (gfx_ypos);
  4660.         if (do_double) {
  4661.         if (gfxvidinfo.linemem == NULL)
  4662.             memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
  4663.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4664.         line_decisions[lineno + 1].which = -2;
  4665.         do_flush_line (follow_ypos);
  4666.         }
  4667.     }
  4668. #ifdef LORES_HACK
  4669.     if (currprefs.gfx_lores == 2)
  4670.         currprefs.gfx_lores = 0;
  4671. #endif
  4672.     } else {
  4673.     /* Border. */
  4674.     int i, lastpos = 0, nextpos;
  4675.     struct color_change *cc;
  4676.  
  4677.     xlinebuffer = gfxvidinfo.linemem;
  4678.     if (xlinebuffer == NULL)
  4679.         xlinebuffer = row_map[gfx_ypos];
  4680.     xlinebuffer -= linetoscr_x_adjust_bytes;
  4681.  
  4682.     adjust_drawing_colors (dp_for_drawing->ctable, 0);
  4683.     /* Check color0 adjust only if we have color changes - shouldn't happen
  4684.      * otherwise. */
  4685.  
  4686.     if (dip_for_drawing->nr_color_changes == 0) {
  4687.         fill_line ();
  4688.         do_flush_line (gfx_ypos);
  4689.         linestate[lineno] = LINE_DONE;
  4690.         if (do_double) {
  4691.         if (gfxvidinfo.linemem == NULL) {
  4692.             xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
  4693.             fill_line ();
  4694.         }
  4695.         do_flush_line (follow_ypos);
  4696.         linestate[lineno+1] = LINE_DONE_AS_PREVIOUS;
  4697.         }
  4698.         return;
  4699.     }
  4700.  
  4701.     adjust_color0_for_color_change ();
  4702.     do_color_changes (pfield_do_fill_line);
  4703.  
  4704.     do_flush_line (gfx_ypos);
  4705.     linestate[lineno] = LINE_DONE;
  4706.     if (do_double) {
  4707.         if (gfxvidinfo.linemem == NULL)
  4708.         memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
  4709.         linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
  4710.         line_decisions[lineno + 1].which = -2;
  4711.         do_flush_line (follow_ypos);
  4712.     }
  4713.     }
  4714. }
  4715.  
  4716. #ifdef SUPPORT_PENGUINS
  4717. static smp_comm_pipe drawing_pipe;
  4718. static uae_sem_t drawing_lock;
  4719.  
  4720. static void *drawing_penguin (void *cruxmedo)
  4721. {
  4722.     int l;
  4723.     fprintf(stderr, "Hello, world!\n");
  4724.  
  4725.     for (;;) {
  4726.     /* Start of a frame. */
  4727.     int k;
  4728.     new_frame:
  4729.     k = read_comm_pipe_int_blocking (&drawing_pipe);
  4730.  
  4731.     switch (k) {
  4732.      case -2:
  4733.         /* Hoopy */
  4734.         break;
  4735.         
  4736.      default:
  4737.         write_log ("Penguin got out of sync.\n");
  4738.         /* what can we do? Try to reduce the damage */
  4739.         for (;;) {
  4740.         k = read_comm_pipe_int_blocking (&drawing_pipe);
  4741.         if (k == -3)
  4742.             break;
  4743.         if (k == -1) {
  4744.             uae_sem_post (&drawing_lock);
  4745.             goto new_frame;
  4746.         }
  4747.         }
  4748.      case -3:
  4749.         UAE_PENGUIN_EXIT;
  4750.         /* Can't happen */
  4751.         return 0;
  4752.     }
  4753.  
  4754.     for (;;) {
  4755.         int i, where;
  4756.         int l = read_comm_pipe_int_blocking (&drawing_pipe);
  4757.         switch (l) {
  4758.          case -1:
  4759.         /* End-of-frame synchronization. */
  4760.         uae_sem_post (&drawing_lock);
  4761.         goto new_frame;
  4762.          case -2:
  4763.         /* customreset called a bit too often. That's harmless. */
  4764.         continue;
  4765.          case -3:
  4766.         write_log ("Penguin got out of sync.\n");
  4767.         UAE_PENGUIN_EXIT;
  4768.         return 0;
  4769.         }
  4770.  
  4771.         /* l is the line that has been finished for drawing. */
  4772.         i = l - thisframe_y_adjust_real;
  4773.         if (i < 0 || i >= max_ypos_thisframe)
  4774.         continue;
  4775.  
  4776.         if (linestate[l] == LINE_UNDECIDED) {
  4777.         fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
  4778.         continue;
  4779.         }
  4780.         if (inhibit_frame > 0)
  4781.         continue;
  4782.         where = amiga2aspect_line_map[i+min_ypos_for_screen];
  4783.         if (where >= gfxvidinfo.maxline || where == -1)
  4784.         continue;
  4785.  
  4786.         pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
  4787.     }
  4788.     }
  4789. }
  4790.  
  4791. static penguin_id our_penguin;
  4792.  
  4793. static void kill_drawing_penguin (void)
  4794. {
  4795.     /* ??? does libpthread do that for us? */
  4796. }
  4797.  
  4798. #endif
  4799.  
  4800. static int penguins_enabled_thisframe;
  4801.  
  4802. static void init_drawing_frame (void)
  4803. {
  4804.     int i, maxline;
  4805.  
  4806. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  4807.     if(delta_sprite_draw) {
  4808.         void *p1,*p2;
  4809.         int mcc = max_sprite_draw + 200 + delta_sprite_draw;
  4810.         delta_sprite_draw = 0;
  4811.         p1 = realloc(sprite_positions[0], mcc*sizeof(struct sprite_draw)); 
  4812.         p2 = realloc(sprite_positions[1], mcc*sizeof(struct sprite_draw)); 
  4813.         if(p1) sprite_positions[0] = p1;
  4814.         if(p2) sprite_positions[1] = p2;
  4815.         if(p1 && p2) {
  4816.             fprintf(stderr,"new max_sprite_draw=%d\n",mcc);
  4817.         max_sprite_draw = mcc;
  4818.     }
  4819.     }
  4820.     if(delta_color_change) {
  4821.         void *p1,*p2;
  4822.         int mcc = max_color_change + 200 + delta_color_change;
  4823.         delta_color_change = 0;
  4824.         p1 = realloc(color_changes[0], mcc*sizeof(struct color_change)); 
  4825.         p2 = realloc(color_changes[1], mcc*sizeof(struct color_change)); 
  4826.         if(p1) color_changes[0] = p1;
  4827.         if(p2) color_changes[1] = p2;
  4828.         if(p1 && p2) {
  4829.             fprintf(stderr,"new max_color_change=%d\n",mcc);
  4830.         max_color_change = mcc;
  4831.         }
  4832.     }
  4833.     if(delta_delay_change) {
  4834.         void *p;
  4835.         int mcc = max_delay_change + 200 + delta_delay_change;
  4836.         delta_delay_change = 0;
  4837.         p = realloc(delay_changes, mcc*sizeof(struct delay_change)); 
  4838.         if(p) {
  4839.             fprintf(stderr,"new max_delay_change=%d\n",mcc);
  4840.         delay_changes = p;
  4841.         max_delay_change = mcc;
  4842.         }
  4843.     }
  4844. #endif
  4845.  
  4846.     if (max_diwstop == 0)
  4847.     max_diwstop = diwlastword;
  4848.     if (min_diwstart > max_diwstop)
  4849.     min_diwstart = 0;
  4850.  
  4851.     if (thisframe_first_drawn_line == -1)
  4852.     thisframe_first_drawn_line = minfirstline;
  4853.     if (thisframe_first_drawn_line > thisframe_last_drawn_line)
  4854.     thisframe_last_drawn_line = thisframe_first_drawn_line;
  4855.  
  4856.     next_color_change = 0;
  4857.     next_delay_change = 0;
  4858.     next_sprite_draw = 0;
  4859.     maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
  4860. #ifdef SMART_UPDATE
  4861.     for (i = 0; i < maxline; i++)
  4862.     linestate[i] = linestate[i] == LINE_DONE_AS_PREVIOUS ? LINE_REMEMBERED_AS_PREVIOUS : LINE_UNDECIDED;
  4863. #else
  4864.     memset (linestate, LINE_UNDECIDED, maxline);
  4865. #endif
  4866.     last_drawn_line = 0;
  4867.     first_drawn_line = 32767;
  4868.  
  4869.     first_block_line = last_block_line = -2;
  4870.     if (currprefs.test_drawing_speed)
  4871.     frame_redraw_necessary = 1;
  4872.     else if (frame_redraw_necessary)
  4873.     frame_redraw_necessary--;
  4874.     
  4875.     next_color_entry = 0;
  4876.     remembered_color_entry = -1;
  4877.     prev_sprite_positions = sprite_positions[current_change_set];
  4878.     curr_sprite_positions = sprite_positions[current_change_set ^ 1];
  4879.     prev_color_changes = color_changes[current_change_set];
  4880.     curr_color_changes = color_changes[current_change_set ^ 1];
  4881.     prev_color_tables = color_tables[current_change_set];
  4882.     curr_color_tables = color_tables[current_change_set ^ 1];
  4883.     
  4884.     prev_drawinfo = line_drawinfo[current_change_set];
  4885.     curr_drawinfo = line_drawinfo[current_change_set ^= 1];
  4886.     drawing_color_matches = -1;
  4887.     color_src_match = color_dest_match = -1;
  4888.  
  4889.     prev_x_adjust = linetoscr_x_adjust;
  4890.     prev_y_adjust = thisframe_y_adjust;
  4891.  
  4892.     if (currprefs.gfx_xcenter) {
  4893.     if (max_diwstop - min_diwstart < gfxvidinfo.maxlinetoscr && currprefs.gfx_xcenter == 2)
  4894.         /* Try to center. */
  4895.         linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.maxlinetoscr) / 2 + min_diwstart) & ~1;
  4896.     else
  4897.         linetoscr_x_adjust = max_diwstop - gfxvidinfo.maxlinetoscr;
  4898.  
  4899.     /* Would the old value be good enough? If so, leave it as it is if we want to
  4900.      * be clever. */
  4901.     if (currprefs.gfx_xcenter == 2) {
  4902.         if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
  4903.         linetoscr_x_adjust = prev_x_adjust;
  4904.     }
  4905.     } else
  4906.     linetoscr_x_adjust = max_diwlastword - gfxvidinfo.maxlinetoscr;
  4907.     if (linetoscr_x_adjust < 0)
  4908.     linetoscr_x_adjust = 0;
  4909.  
  4910.     linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
  4911.  
  4912.     linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.maxlinetoscr;
  4913.     if (linetoscr_right_x > max_diwlastword)
  4914.     linetoscr_right_x = max_diwlastword;
  4915.  
  4916.     thisframe_y_adjust = minfirstline;
  4917.     if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
  4918.     if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
  4919.         thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
  4920.     else
  4921.         thisframe_y_adjust = thisframe_first_drawn_line;
  4922.     /* Would the old value be good enough? If so, leave it as it is if we want to
  4923.      * be clever. */
  4924.     if (currprefs.gfx_ycenter == 2) {
  4925.         if (thisframe_y_adjust != prev_y_adjust
  4926.         && prev_y_adjust <= thisframe_first_drawn_line
  4927.         && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
  4928.         thisframe_y_adjust = prev_y_adjust;
  4929.     }
  4930.     /* Make sure the value makes sense */
  4931.     if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
  4932.         thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
  4933.     if (thisframe_y_adjust < minfirstline)
  4934.         thisframe_y_adjust = minfirstline;
  4935.     }
  4936.     thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
  4937.     max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
  4938.  
  4939.     if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
  4940.     frame_redraw_necessary |= (bplcon0 & 4) && currprefs.gfx_linedbl ? 2 : 1;
  4941.  
  4942.     max_diwstop = 0;
  4943.     min_diwstart = 10000;
  4944.     thisframe_first_drawn_line = -1;
  4945.     thisframe_last_drawn_line = -1;
  4946. #ifdef SUPPORT_PENGUINS
  4947.     penguins_enabled_thisframe = 1;
  4948.     /* Tell the other thread that it can now expect data from us. */
  4949.     write_comm_pipe_int (&drawing_pipe, -2, 1);
  4950.     memset (line_drawn, 0, sizeof line_drawn);
  4951. #endif
  4952. }
  4953.  
  4954. static void finish_drawing_frame (void)
  4955. {
  4956.     int i;
  4957.  
  4958. #ifdef SUPPORT_PENGUINS
  4959.     /* Synchronize with other thread, then see whether there's something left for
  4960.      * us to draw. @@@ This is probably a big waste of cycles if the two threads
  4961.      * run at very different speeds - this one could draw stuff as well. */
  4962.     write_comm_pipe_int (&drawing_pipe, -1, 1);
  4963.     uae_sem_wait (&drawing_lock);
  4964. #else
  4965.  
  4966. #ifndef SMART_UPDATE
  4967.     /* @@@ This isn't exactly right yet. FIXME */
  4968.     if (!interlace_seen) {
  4969.     do_flush_screen (first_drawn_line, last_drawn_line);
  4970.     return;
  4971.     }
  4972. #endif
  4973.     for (i = 0; i < max_ypos_thisframe; i++) {
  4974.     int where;
  4975.     int line = i + thisframe_y_adjust_real;
  4976.  
  4977.     if (linestate[line] == LINE_UNDECIDED)
  4978.         break;
  4979.  
  4980.     where = amiga2aspect_line_map[i+min_ypos_for_screen];
  4981.     if (where >= gfxvidinfo.maxline)
  4982.         break;
  4983.     if (where == -1)
  4984.         continue;
  4985.  
  4986.     pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
  4987.     }
  4988. #endif
  4989.     do_flush_screen (first_drawn_line, last_drawn_line);
  4990. }
  4991.  
  4992. static void vsync_handler (void)
  4993. {
  4994.     static int cnt = 0;
  4995.     uae_u16 dir;
  4996.     int button;
  4997.  
  4998. #ifdef FRAME_RATE_HACK /* put this here or at the end of the function? */
  4999.     {
  5000.     frame_time_t curr_time = read_processor_time();
  5001.     vsyncmintime += vsynctime;
  5002.     /* @@@ Mathias? How do you think we should do this? */
  5003.     /* If we are too far behind, or we just did a reset, adjust the
  5004.      * needed time. */
  5005.     if ((long int)(curr_time - vsyncmintime) > 0 || did_reset)
  5006.         vsyncmintime = curr_time + vsynctime;
  5007.     did_reset = 0;
  5008.     }
  5009. #endif
  5010.     handle_events ();
  5011.     if (cnt == 0) {
  5012.     DISK_check_change ();
  5013.     cnt = 5;
  5014.     }
  5015.     cnt--;
  5016.  
  5017.     getjoystate (0, &joy0dir, &joy0button);
  5018.     getjoystate (1, &joy1dir, &joy1button);
  5019.  
  5020.     do_mouse_hack();
  5021.     
  5022.     INTREQ(0x8020);
  5023.     if (bplcon0 & 4) 
  5024.     lof ^= 0x8000;
  5025.  
  5026.     if (quit_program < 0) {
  5027.     quit_program = -quit_program;
  5028.     inhibit_frame = 2;
  5029.     regs.spcflags |= SPCFLAG_BRK;
  5030.     if (framecnt == 0)
  5031.         finish_drawing_frame ();
  5032.     filesys_prepare_reset ();
  5033. #ifdef SUPPORT_PENGUINS
  5034.     if (quit_program == 1)
  5035.         /* Stop eating herring */
  5036.         write_comm_pipe_int (&drawing_pipe, -3, 1);
  5037. #endif
  5038.     return;
  5039.     }
  5040.  
  5041.     last_redraw_point++;
  5042.     if (lof_changed || !interlace_seen || last_redraw_point >= 2 || lof) {
  5043.     if (framecnt == 0)
  5044.         finish_drawing_frame ();
  5045.     count_frame ();
  5046.     last_redraw_point = 0;
  5047.     /* There may be reasons why we want to override count_frame()'s
  5048.      * decision. */
  5049.     if (inhibit_frame > 0)
  5050.         framecnt = 1;
  5051.     else {
  5052.         
  5053.     }
  5054.     if (framecnt == 0)
  5055.         init_drawing_frame ();
  5056.     }
  5057.     
  5058.     lof_changed = 0;
  5059.     interlace_seen = 0;
  5060.     COPJMP1(0);
  5061.     
  5062.     init_hardware_frame();
  5063. #ifdef HAVE_GETTIMEOFDAY
  5064.     {
  5065.     struct timeval tv;
  5066.     unsigned long int newtime;
  5067.     
  5068.     gettimeofday(&tv,NULL);    
  5069.     newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
  5070.     
  5071.     if (!bogusframe) {    
  5072.         frametime += newtime - msecs;
  5073.         timeframes++;
  5074.     }
  5075.     msecs = newtime;
  5076.     bogusframe = 0;
  5077.     }
  5078. #endif
  5079.     if (ievent_alive > 0)
  5080.     ievent_alive--;
  5081.     CIA_vsync_handler();
  5082. }
  5083.  
  5084. static void hsync_handler(void)
  5085. {
  5086.     int lineno = next_lineno;
  5087.     int lineisdouble = 0;
  5088.     int line_was_doubled = 0;
  5089.     
  5090.     finish_decisions ();
  5091.     do_modulos ();
  5092.  
  5093.     if (framecnt == 0) {
  5094.     switch (nln_how) {
  5095.      case 0:
  5096.         linestate[lineno] = LINE_DECIDED;
  5097.         break;
  5098.      case 1:
  5099.         linestate[lineno] = LINE_DECIDED_DOUBLE;
  5100.         if (linestate[lineno+1] != LINE_REMEMBERED_AS_PREVIOUS)
  5101.         linestate[lineno+1] = LINE_AS_PREVIOUS;
  5102.         break;
  5103.      case 2:
  5104.         if (linestate[lineno-1] == LINE_UNDECIDED)
  5105.         linestate[lineno-1] = LINE_BORDER_NEXT;
  5106.         linestate[lineno] = LINE_DECIDED;
  5107.         break;
  5108.      case 3:
  5109.         linestate[lineno] = LINE_DECIDED;
  5110.         if (linestate[lineno+1] == LINE_UNDECIDED
  5111.         || linestate[lineno+1] == LINE_REMEMBERED_AS_PREVIOUS
  5112.         || linestate[lineno+1] == LINE_AS_PREVIOUS)
  5113.         linestate[lineno+1] = LINE_BORDER_PREV;
  5114.         break;
  5115.     }
  5116.     }
  5117.  
  5118.     eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles;
  5119.     eventtab[ev_hsync].oldcycles = cycles;
  5120.     CIA_hsync_handler();
  5121.     
  5122.     if (currprefs.produce_sound > 0) {
  5123.     int nr;
  5124.     /* Sound data is fetched at the beginning of each line */
  5125.     for (nr = 0; nr < 4; nr++) {
  5126.         struct audio_channel_data *cdp = audio_channel + nr;
  5127.         
  5128.         if (cdp->data_written == 2) {
  5129.         cdp->data_written = 0;
  5130.         cdp->nextdat = chipmem_bank.wget(cdp->pt);
  5131.         cdp->pt += 2;
  5132.         if (cdp->state == 2 || cdp->state == 3) {
  5133.             if (cdp->wlen == 1) {
  5134.             cdp->pt = cdp->lc;
  5135.             cdp->wlen = cdp->len;
  5136.             cdp->intreq2 = 1;
  5137.             } else
  5138.             cdp->wlen--;
  5139.         }
  5140.         }
  5141.     }
  5142.     }
  5143. #ifdef SUPPORT_PENGUINS
  5144.     if (framecnt == 0 && penguins_enabled_thisframe) {
  5145.     write_comm_pipe_int (&drawing_pipe, next_lineno, 0);
  5146.     }
  5147. #endif
  5148. #ifndef SMART_UPDATE
  5149.     {
  5150.     int i, where;
  5151.     /* l is the line that has been finished for drawing. */
  5152.     i = next_lineno - thisframe_y_adjust_real;
  5153.     if (i >= 0 && i < max_ypos_thisframe) {
  5154.         where = amiga2aspect_line_map[i+min_ypos_for_screen];
  5155.         if (where < gfxvidinfo.maxline && where != -1)
  5156.         pfield_draw_line (next_lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
  5157.     }
  5158.     }
  5159. #endif
  5160.     if (++vpos == (maxvpos + (lof != 0))) {
  5161.     vpos = 0;
  5162.     vsync_handler();
  5163.     }
  5164.  
  5165.     is_lastline = vpos + 1 == maxvpos + (lof != 0);
  5166.  
  5167.     if ((bplcon0 & 4) && currprefs.gfx_linedbl) {
  5168.     interlace_seen = 1, penguins_enabled_thisframe = 0;
  5169.     }
  5170.  
  5171.     if (framecnt == 0) {
  5172.     lineno = vpos;
  5173.     nln_how = 0;
  5174.     if (currprefs.gfx_linedbl) {
  5175.         lineno *= 2;
  5176.         nln_how = 1;
  5177.         if (bplcon0 & 4) {
  5178.         if (!lof) {
  5179.             lineno++;
  5180.             nln_how = 2;
  5181.         } else {
  5182.             nln_how = 3;
  5183.         }
  5184.         }
  5185.     }
  5186.     next_lineno = lineno;
  5187.     reset_decisions ();
  5188.     }
  5189.     if (uae_int_requested) {
  5190.     set_uae_int_flag ();
  5191.     INTREQ (0xA000);
  5192.     }
  5193. }
  5194.  
  5195. void customreset(void)
  5196. {
  5197.     int i, maxl;
  5198.     double native_lines_per_amiga_line;
  5199. #ifdef HAVE_GETTIMEOFDAY
  5200.     struct timeval tv;
  5201. #endif
  5202.  
  5203.     for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++)
  5204.     current_colors.color_regs[i] = -1;
  5205.  
  5206. #ifdef FRAME_RATE_HACK
  5207.     did_reset = 1;
  5208.     vsyncmintime = read_processor_time() + vsynctime;
  5209. #endif
  5210.     inhibit_frame = 0;
  5211.     expamem_reset ();
  5212.     filesys_reset ();
  5213.     CIA_reset ();
  5214.     cycles = 0; 
  5215.     regs.spcflags &= SPCFLAG_BRK;
  5216.     
  5217.     lores_factor = currprefs.gfx_lores ? 1 : 2;
  5218.     lores_shift = currprefs.gfx_lores ? 0 : 1;
  5219.     sprite_width = currprefs.gfx_lores ? 16 : 32;
  5220.     
  5221.     vpos = 0;
  5222.     is_lastline = 0;
  5223.     lof = 0;
  5224.     max_diwstop = 0;
  5225.     
  5226.     if (needmousehack()) {
  5227. #if 1/* 0 ATB XXXXX */
  5228.         if (mousestate != follow_mouse) setfollow();
  5229. #else
  5230.         if (mousestate != dont_care_mouse) setdontcare();
  5231. #endif
  5232.     } else {
  5233.     mousestate = normal_mouse;
  5234.     }
  5235.     ievent_alive = 0;
  5236.  
  5237.     clx_sprmask = 0xFF;    
  5238.     clxdat = 0;
  5239.     
  5240.     memset(sprarmed, 0, sizeof sprarmed);
  5241.     nr_armed = 0;
  5242.     
  5243.     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
  5244.     for (i = 0; i < (maxvpos+1)*2 + 1; i++) {
  5245.     linestate[i] = LINE_UNDECIDED;
  5246.     }
  5247.     xlinebuffer = gfxvidinfo.bufmem;
  5248.  
  5249.     dmacon = intena = 0;
  5250.     bltstate = BLT_done;
  5251.     copstate = COP_stop;
  5252.     diwstate = DIW_waiting_start;
  5253.     hdiwstate = DIW_waiting_start;
  5254.     copcon = 0;
  5255.     dskdmaen = 0;
  5256.     cycles = 0;
  5257.     
  5258.     memset(audio_channel, 0, sizeof audio_channel);
  5259.  
  5260.     bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
  5261.     bplcon3 = 0xC00;
  5262.     for(i = 0; i < ev_max; i++) {
  5263.     eventtab[i].active = 0;
  5264.     eventtab[i].oldcycles = 0;
  5265.     }
  5266.     copper_active = 0;
  5267.     eventtab[ev_cia].handler = CIA_handler;
  5268.     eventtab[ev_copper].handler = currprefs.copper_pos < 0 ? do_copper : do_copper_cheat;
  5269.     eventtab[ev_hsync].handler = hsync_handler;
  5270.     eventtab[ev_hsync].evtime = maxhpos + cycles;
  5271.     eventtab[ev_hsync].active = 1;
  5272.  
  5273.     eventtab[ev_blitter].handler = blitter_handler;
  5274.     eventtab[ev_blitter].active = 0;
  5275.     eventtab[ev_diskblk].handler = diskblk_handler;
  5276.     eventtab[ev_diskblk].active = 0;
  5277.     eventtab[ev_diskindex].handler = diskindex_handler;
  5278.     eventtab[ev_diskindex].active = 0;
  5279. #ifndef DONT_WANT_SOUND
  5280.     eventtab[ev_aud0].handler = aud0_handler;
  5281.     eventtab[ev_aud0].active = 0;
  5282.     eventtab[ev_aud1].handler = aud1_handler;
  5283.     eventtab[ev_aud1].active = 0;
  5284.     eventtab[ev_aud2].handler = aud2_handler;
  5285.     eventtab[ev_aud2].active = 0;
  5286.     eventtab[ev_aud3].handler = aud3_handler;
  5287.     eventtab[ev_aud3].active = 0;
  5288.     if (sound_available && currprefs.produce_sound >= 2) {
  5289.     eventtab[ev_sample].active = 1;
  5290.     eventtab[ev_sample].evtime = sample_evtime;
  5291.     } else {
  5292.     eventtab[ev_sample].active = 0;
  5293.     }
  5294. #endif
  5295.     events_schedule ();
  5296.  
  5297.     if (native2amiga_line_map)
  5298.     free (native2amiga_line_map);
  5299.     if (amiga2aspect_line_map)
  5300.     free (amiga2aspect_line_map);
  5301.  
  5302.     /* At least for this array the +1 is necessary. */ 
  5303.     amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
  5304.     native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.maxline);
  5305.  
  5306.     if (currprefs.gfx_correct_aspect)
  5307.     native_lines_per_amiga_line = ((double)gfxvidinfo.maxline
  5308.                        * (currprefs.gfx_lores ? 320 : 640)
  5309.                        / (currprefs.gfx_linedbl ? 512 : 256)
  5310.                        / gfxvidinfo.maxlinetoscr);
  5311.     else
  5312.     native_lines_per_amiga_line = 1;
  5313.  
  5314.     maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
  5315.     min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
  5316.     max_drawn_amiga_line = -1;
  5317.     for (i = 0; i < maxl; i++) {
  5318.     int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
  5319.     if (v >= gfxvidinfo.maxline && max_drawn_amiga_line == -1)
  5320.         max_drawn_amiga_line = i-min_ypos_for_screen;
  5321.     if (i < min_ypos_for_screen || v >= gfxvidinfo.maxline)
  5322.         v = -1;
  5323.     amiga2aspect_line_map[i] = v;
  5324.     }
  5325.     if (currprefs.gfx_linedbl)
  5326.     max_drawn_amiga_line >>= 1;
  5327.  
  5328.     if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
  5329.     extra_y_adjust = (gfxvidinfo.maxline - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
  5330.     if (extra_y_adjust < 0)
  5331.         extra_y_adjust = 0;
  5332.     }
  5333.  
  5334.     for (i = 0; i < gfxvidinfo.maxline; i++)
  5335.     native2amiga_line_map[i] = -1;
  5336.  
  5337.     if (native_lines_per_amiga_line < 1) {
  5338.     /* Must omit drawing some lines. */
  5339.     for (i = maxl-1; i > min_ypos_for_screen; i--) {
  5340.         if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
  5341.         if (currprefs.gfx_linedbl && (i & 1) == 0  && amiga2aspect_line_map[i+1] != -1) {
  5342.             /* If only the first line of a line pair would be omitted,
  5343.              * omit the second one instead to avoid problems with line
  5344.              * doubling. */
  5345.             amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
  5346.             amiga2aspect_line_map[i+1] = -1;
  5347.         } else
  5348.             amiga2aspect_line_map[i] = -1;
  5349.         }
  5350.     }
  5351.     }
  5352.  
  5353.     for (i = maxl-1; i >= min_ypos_for_screen; i--) {
  5354.     int j;
  5355.     if (amiga2aspect_line_map[i] == -1)
  5356.         continue;
  5357.     for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.maxline && native2amiga_line_map[j] == -1; j++)
  5358.         native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
  5359.     }
  5360.     
  5361.     if (line_drawn == 0)
  5362.     line_drawn = (char *)malloc (gfxvidinfo.maxline);
  5363.     if (row_map != 0)
  5364.     free (row_map);
  5365.     row_map = (char **)malloc (sizeof (char *) * (gfxvidinfo.maxline+1));
  5366.     init_row_map();
  5367.     init_hardware_frame ();
  5368.     init_drawing_frame ();
  5369.     last_redraw_point = 0;
  5370.     reset_decisions ();
  5371. #ifdef HAVE_GETTIMEOFDAY
  5372.     gettimeofday(&tv,NULL);
  5373.     seconds_base = tv.tv_sec;
  5374.     bogusframe = 1;
  5375. #endif
  5376. }
  5377.  
  5378. void dumpcustom(void)
  5379. {
  5380.     int i;
  5381.     fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
  5382.        intena, intreq, vpos, current_hpos());
  5383.     if (timeframes) { 
  5384.     fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n", 
  5385.            frametime/timeframes, timeframes, frametime);
  5386.     }
  5387.     /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]);  blitter debug */
  5388. }
  5389.  
  5390. int intlev(void)
  5391. {
  5392.     uae_u16 imask = intreq & intena;
  5393.     if (imask && (intena & 0x4000)){
  5394.     if (imask & 0x2000) return 6;
  5395.     if (imask & 0x1800) return 5;
  5396.     if (imask & 0x0780) return 4;
  5397.     if (imask & 0x0070) return 3;
  5398.     if (imask & 0x0008) return 2;
  5399.     if (imask & 0x0007) return 1;
  5400.     }
  5401.     return -1;
  5402. }
  5403.  
  5404. void custom_init(void)
  5405. {
  5406.     int num;
  5407.  
  5408. #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
  5409.     for(num=0;num<2;++num) {
  5410.        sprite_positions[num] = malloc(max_sprite_draw * sizeof(struct sprite_draw));
  5411.        color_changes[num] = malloc(max_color_change * sizeof(struct color_change));
  5412.        if(!sprite_positions[num] || !color_changes[num]) {
  5413.              printf("Out of mem in %s %d!\n",__FILE__,__LINE__);
  5414.              abort();
  5415.        }
  5416.     }
  5417.     if(!(delay_changes = malloc(max_delay_change * sizeof(struct delay_change)))) {
  5418.        printf("Out of mem int %s %d!\n",__FILE__,__LINE__);
  5419.        abort();
  5420.     }
  5421. #endif
  5422.     
  5423.     if (needmousehack())
  5424.     setfollow();
  5425.     init_regchanges ();
  5426.     init_decisions ();
  5427.  
  5428.     /* For now, the AGA stuff is broken in the dual playfield case. We encode
  5429.      * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
  5430.      * playfield rendering easy, the lookup tables contain are made linear for
  5431.      * values >= 128. That only works for OCS/ECS, though. */
  5432.     
  5433.     for (num = 0; num < 256; num++) {    
  5434.     int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8);
  5435.     int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8);
  5436.     dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
  5437.     dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
  5438.     if (plane2 > 0) plane2 += 8;
  5439.     dblpf_ind1[num] = num >= 128 ? num & 0x7F : (plane1 == 0 ? plane2 : plane1);
  5440.     dblpf_ind2[num] = num >= 128 ? num & 0x7F : (plane2 == 0 ? plane1 : plane2);
  5441.     
  5442.     lots_of_twos[num] = num == 0 ? 0 : 2;
  5443.     linear_map_256[num] = num;
  5444.     }
  5445.     build_blitfilltable();
  5446.     gen_pfield_tables();
  5447.     native2amiga_line_map = 0;
  5448.     amiga2aspect_line_map = 0;
  5449.     line_drawn = 0;
  5450.     row_map = 0;
  5451.  
  5452. #ifdef SUPPORT_PENGUINS
  5453.     init_comm_pipe (&drawing_pipe, 800, 5);
  5454.     uae_sem_init (&drawing_lock, 0, 0);
  5455.     start_penguin (drawing_penguin, 0, &our_penguin);
  5456.     /*atexit(kill_drawing_penguin);*/
  5457. #endif
  5458. }
  5459.  
  5460. /* Custom chip memory bank */
  5461.  
  5462. static uae_u32 custom_lget(uaecptr) REGPARAM;
  5463. static uae_u32 custom_wget(uaecptr) REGPARAM;
  5464. static uae_u32 custom_bget(uaecptr) REGPARAM;
  5465. static void  custom_lput(uaecptr, uae_u32) REGPARAM;
  5466. static void  custom_wput(uaecptr, uae_u32) REGPARAM;
  5467. static void  custom_bput(uaecptr, uae_u32) REGPARAM;
  5468.  
  5469. addrbank custom_bank = {
  5470.     custom_lget, custom_wget, custom_bget,
  5471.     custom_lput, custom_wput, custom_bput,
  5472.     default_xlate, default_check
  5473. };
  5474.  
  5475. uae_u32 REGPARAM2 custom_wget(uaecptr addr)
  5476. {
  5477.     switch(addr & 0x1FE) {
  5478.      case 0x002: return DMACONR();
  5479.      case 0x004: return VPOSR();
  5480.      case 0x006: return VHPOSR();
  5481.     
  5482.      case 0x008: return DSKDATR();
  5483.  
  5484.      case 0x00A: return JOY0DAT();
  5485.      case 0x00C: return JOY1DAT();
  5486.      case 0x00E: return CLXDAT();
  5487.      case 0x010: return ADKCONR();
  5488.  
  5489.      case 0x012: return POT0DAT();
  5490.      case 0x016: return POTGOR();
  5491.      case 0x018: return SERDATR();
  5492.      case 0x01A: return DSKBYTR();
  5493.      case 0x01C: return INTENAR();
  5494.      case 0x01E: return INTREQR();
  5495. #if AGA_CHIPSET == 1
  5496.      case 0x07C: return 0xF8;
  5497. #elif defined ECS_DENISE
  5498.      case 0x07C: return 0xFC;
  5499. #endif
  5500.      default:
  5501.     custom_wput(addr,0);
  5502.     return 0xffff;
  5503.     }
  5504. }
  5505.  
  5506. uae_u32 REGPARAM2 custom_bget(uaecptr addr)
  5507. {
  5508.     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
  5509. }
  5510.  
  5511. uae_u32 REGPARAM2 custom_lget(uaecptr addr)
  5512. {
  5513.     return ((uae_u32)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
  5514. }
  5515.  
  5516. void REGPARAM2 custom_wput(uaecptr addr, uae_u32 value)
  5517. {
  5518.     addr &= 0x1FE;
  5519.     cregs[addr>>1] = value;
  5520.     switch(addr) {    
  5521.      case 0x020: DSKPTH(value); break;
  5522.      case 0x022: DSKPTL(value); break;
  5523.      case 0x024: DSKLEN(value); break;
  5524.      case 0x026: DSKDAT(value); break;
  5525.     
  5526.      case 0x02A: VPOSW(value); break;
  5527.      case 0x2E:  COPCON(value); break;
  5528.      case 0x030: SERDAT(value); break;
  5529.      case 0x032: SERPER(value); break;
  5530.  
  5531.      case 0x040: BLTCON0(value); break;
  5532.      case 0x042: BLTCON1(value); break;
  5533.     
  5534.      case 0x044: BLTAFWM(value); break;
  5535.      case 0x046: BLTALWM(value); break;
  5536.     
  5537.      case 0x050: BLTAPTH(value); break;
  5538.      case 0x052: BLTAPTL(value); break;
  5539.      case 0x04C: BLTBPTH(value); break;
  5540.      case 0x04E: BLTBPTL(value); break;
  5541.      case 0x048: BLTCPTH(value); break;
  5542.      case 0x04A: BLTCPTL(value); break;
  5543.      case 0x054: BLTDPTH(value); break;
  5544.      case 0x056: BLTDPTL(value); break;
  5545.     
  5546.      case 0x058: BLTSIZE(value); break;
  5547.     
  5548.      case 0x064: BLTAMOD(value); break;
  5549.      case 0x062: BLTBMOD(value); break;
  5550.      case 0x060: BLTCMOD(value); break;
  5551.      case 0x066: BLTDMOD(value); break;
  5552.     
  5553.      case 0x070: BLTCDAT(value); break;
  5554.      case 0x072: BLTBDAT(value); break;
  5555.      case 0x074: BLTADAT(value); break;
  5556.             
  5557.      case 0x07E: DSKSYNC(value); break;
  5558.  
  5559.      case 0x080: COP1LCH(value); break;
  5560.      case 0x082: COP1LCL(value); break;
  5561.      case 0x084: COP2LCH(value); break;
  5562.      case 0x086: COP2LCL(value); break;
  5563.     
  5564.      case 0x088: COPJMP1(value); break;
  5565.      case 0x08A: COPJMP2(value); break;
  5566.     
  5567.      case 0x08E: DIWSTRT(value); break;
  5568.      case 0x090: DIWSTOP(value); break;
  5569.      case 0x092: DDFSTRT(value); break;
  5570.      case 0x094: DDFSTOP(value); break;
  5571.     
  5572.      case 0x096: DMACON(value); break;
  5573.      case 0x098: CLXCON(value); break;
  5574.      case 0x09A: INTENA(value); break;
  5575.      case 0x09C: INTREQ(value); break;
  5576.      case 0x09E: ADKCON(value); break;
  5577.     
  5578.      case 0x0A0: AUDxLCH(0, value); break;
  5579.      case 0x0A2: AUDxLCL(0, value); break;
  5580.      case 0x0A4: AUDxLEN(0, value); break;
  5581.      case 0x0A6: AUDxPER(0, value); break;
  5582.      case 0x0A8: AUDxVOL(0, value); break;
  5583.      case 0x0AA: AUDxDAT(0, value); break;
  5584.     
  5585.      case 0x0B0: AUDxLCH(1, value); break;
  5586.      case 0x0B2: AUDxLCL(1, value); break;
  5587.      case 0x0B4: AUDxLEN(1, value); break;
  5588.      case 0x0B6: AUDxPER(1, value); break;
  5589.      case 0x0B8: AUDxVOL(1, value); break;
  5590.      case 0x0BA: AUDxDAT(1, value); break;
  5591.     
  5592.      case 0x0C0: AUDxLCH(2, value); break;
  5593.      case 0x0C2: AUDxLCL(2, value); break;
  5594.      case 0x0C4: AUDxLEN(2, value); break;
  5595.      case 0x0C6: AUDxPER(2, value); break;
  5596.      case 0x0C8: AUDxVOL(2, value); break;
  5597.      case 0x0CA: AUDxDAT(2, value); break;
  5598.     
  5599.      case 0x0D0: AUDxLCH(3, value); break;
  5600.      case 0x0D2: AUDxLCL(3, value); break;
  5601.      case 0x0D4: AUDxLEN(3, value); break;
  5602.      case 0x0D6: AUDxPER(3, value); break;
  5603.      case 0x0D8: AUDxVOL(3, value); break;
  5604.      case 0x0DA: AUDxDAT(3, value); break;
  5605.     
  5606.      case 0x0E0: BPLPTH(value, 0); break;
  5607.      case 0x0E2: BPLPTL(value, 0); break;
  5608.      case 0x0E4: BPLPTH(value, 1); break;
  5609.      case 0x0E6: BPLPTL(value, 1); break;
  5610.      case 0x0E8: BPLPTH(value, 2); break;
  5611.      case 0x0EA: BPLPTL(value, 2); break;
  5612.      case 0x0EC: BPLPTH(value, 3); break;
  5613.      case 0x0EE: BPLPTL(value, 3); break;
  5614.      case 0x0F0: BPLPTH(value, 4); break;
  5615.      case 0x0F2: BPLPTL(value, 4); break;
  5616.      case 0x0F4: BPLPTH(value, 5); break;
  5617.      case 0x0F6: BPLPTL(value, 5); break;
  5618.     
  5619.      case 0x100: BPLCON0(value); break;
  5620.      case 0x102: BPLCON1(value); break;
  5621.      case 0x104: BPLCON2(value); break;
  5622.      case 0x106: BPLCON3(value); break;
  5623.     
  5624.      case 0x108: BPL1MOD(value); break;
  5625.      case 0x10A: BPL2MOD(value); break;
  5626.  
  5627.      case 0x110: BPL1DAT(value); break;
  5628.      case 0x112: BPL2DAT(value); break;
  5629.      case 0x114: BPL3DAT(value); break;
  5630.      case 0x116: BPL4DAT(value); break;
  5631.      case 0x118: BPL5DAT(value); break;
  5632.      case 0x11A: BPL6DAT(value); break;
  5633.     
  5634.      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
  5635.      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
  5636.      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
  5637.      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
  5638.      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
  5639.      case 0x1BC: case 0x1BE:
  5640.     COLOR(value & 0xFFF, (addr & 0x3E) / 2);
  5641.     break;
  5642.      case 0x120: case 0x124: case 0x128: case 0x12C:
  5643.      case 0x130: case 0x134: case 0x138: case 0x13C:
  5644.     SPRxPTH(value, (addr - 0x120) / 4);
  5645.     break;
  5646.      case 0x122: case 0x126: case 0x12A: case 0x12E:
  5647.      case 0x132: case 0x136: case 0x13A: case 0x13E:
  5648.     SPRxPTL(value, (addr - 0x122) / 4);
  5649.     break;
  5650.      case 0x140: case 0x148: case 0x150: case 0x158:
  5651.      case 0x160: case 0x168: case 0x170: case 0x178:
  5652.     SPRxPOS(value, (addr - 0x140) / 8);
  5653.     break;
  5654.      case 0x142: case 0x14A: case 0x152: case 0x15A:
  5655.      case 0x162: case 0x16A: case 0x172: case 0x17A:
  5656.     SPRxCTL(value, (addr - 0x142) / 8);
  5657.     break;
  5658.      case 0x144: case 0x14C: case 0x154: case 0x15C:
  5659.      case 0x164: case 0x16C: case 0x174: case 0x17C:
  5660.     SPRxDATA(value, (addr - 0x144) / 8);
  5661.     break;
  5662.      case 0x146: case 0x14E: case 0x156: case 0x15E:
  5663.      case 0x166: case 0x16E: case 0x176: case 0x17E:
  5664.     SPRxDATB(value, (addr - 0x146) / 8);
  5665.     break;
  5666.     
  5667.      case 0x36: JOYTEST(value); break;
  5668. #if defined(ECS_AGNUS) || (AGA_CHIPSET == 1)
  5669.      case 0x5A: BLTCON0L(value); break;
  5670.      case 0x5C: BLTSIZV(value); break;
  5671.      case 0x5E: BLTSIZH(value); break;
  5672. #endif
  5673. #if AGA_CHIPSET == 1
  5674.      case 0x10C: BPLCON4(value); break;
  5675.      case 0x1FC: fmode = value; break;
  5676. #endif
  5677.     }
  5678. }
  5679.  
  5680. void REGPARAM2 custom_bput(uaecptr addr, uae_u32 value)
  5681. {
  5682.     static int warned = 0;
  5683.     /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
  5684.     uae_u16 rval = (value << 8) | (value & 0xFF);
  5685.     custom_wput(addr, rval);
  5686.     if (!warned)
  5687.     write_log ("Byte put to custom register.\n"), warned++;
  5688. }
  5689.  
  5690. void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
  5691. {
  5692.     custom_wput(addr & 0xfffe, value >> 16);
  5693.     custom_wput((addr+2) & 0xfffe, (uae_u16)value);
  5694. }
  5695.